Get fully qualified class name of an object in Python
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
In Python, the fully qualified class name of an object is usually the module name plus the class name. That is useful in logging, plugin systems, debugging output, and serialization metadata because it identifies the class more precisely than __name__ alone.
Basic Approach
For most objects, you can get the class from obj.__class__, then combine __module__ with __qualname__.
If Example is defined in a module named myapp.models, the result would look like:
This is usually the best default because __qualname__ preserves nesting information for inner classes better than __name__.
Why __qualname__ Is Better Than __name__
__name__ gives only the immediate class name. __qualname__ includes the path inside the module for nested definitions.
If you are generating a fully qualified identifier, __qualname__ is more informative and less likely to lose structure.
Handling Built-in Types
Built-in types still follow the same rule, but their module is often builtins.
Some applications prefer to omit the builtins. prefix for readability. That is a formatting choice, not a requirement.
A Reusable Utility Function
If you want built-ins to appear without the module prefix, make that explicit in a helper:
This keeps your logging format consistent instead of scattering ad hoc string building across the codebase.
Objects vs Classes
Be careful whether your function receives an instance or a class object. If you pass a class itself, obj.__class__ becomes type, which is not what you want.
A more defensive helper can support both:
That small distinction prevents confusing output when reflective code works with a mix of instances and classes.
When a Qualified Name Is Not Enough
A fully qualified class name is useful for diagnostics, but it is not always a perfect serialization key. Classes can move between modules during refactors, and some dynamically generated classes may have names that are technically correct but awkward for storage or interoperability.
That means the pattern is excellent for logging and debugging, but more fragile as a long-term persistence format unless your application controls module stability carefully.
Logging and Plugin Use Cases
This technique is especially helpful in frameworks that load handlers, strategies, or plugins dynamically. Logging qualified_name(plugin) gives you a stable human-readable identifier that is far better than the default object representation when you are tracing configuration issues.
It is also useful during debugging sessions where inheritance chains matter. Seeing package.subpackage.CustomCache in logs immediately tells you more than simply seeing CustomCache, especially in large projects with repeated class names across modules.
Common Pitfalls
- Using only
__name__and losing module context when different modules define classes with the same name. - Using
__class__on a class object and accidentally gettingtypeinstead of the intended class. - Preferring
__name__over__qualname__when nested classes are possible. - Assuming the fully qualified name is always stable enough for long-term serialization contracts.
- Hard-coding string formatting logic in multiple places instead of centralizing it in one helper.
Summary
- The usual fully qualified class name is
__module__plus__qualname__. - '
__qualname__is more informative than__name__, especially for nested classes.' - Built-in types often produce names such as
builtins.int. - If code may receive either instances or classes, handle both explicitly.
- A small helper function keeps class-name formatting consistent across the codebase.

