214

For logging purposes I want to retrieve the fully qualified class name of a Python object. (With fully qualified I mean the class name including the package and module name.)

I know about x.__class__.__name__, but is there a simple method to get the package and module?

1
  • str(MyClass)[8:-2] Commented Sep 1, 2024 at 12:21

14 Answers 14

233

With the following program

#!/usr/bin/env python import foo def fullname(o): klass = o.__class__ module = klass.__module__ if module == 'builtins': return klass.__qualname__ # avoid outputs like 'builtins.str' return module + '.' + klass.__qualname__ bar = foo.Bar() print(fullname(bar)) 

and Bar defined as

class Bar(object): def __init__(self, v=42): self.val = v 

the output is

$ ./prog.py foo.Bar 

If you're still stuck on Python 2, you'll have to use __name__ instead of __qualname__, which is less informative for nested classes - a class Bar nested in a class Foo will show up as Bar instead of Foo.Bar:

def fullname(o): klass = o.__class__ module = klass.__module__ if module == '__builtin__': return klass.__name__ # avoid outputs like '__builtin__.str' return module + '.' + klass.__name__ 
Sign up to request clarification or add additional context in comments.

5 Comments

This appears to return the module where bar was defined, not where Bar was defined. If the purpose of logging is to know exactly what kind of object it was, then this doesn't seem to help.
Is o.__class__.__module__ ever different from o.__module__?
I strongly recomend ".".join([o.__module__, o.__name__]) for Python3
Doesn't work sometimes: AttributeError: 'AttributeError' object has no attribute '__module__'
67

The provided answers don't deal with nested classes.

Since Python 3.3 (PEP 3155), you can use __qualname__ of the class instead of the __name__. Otherwise, a class like

class Foo: class Bar: # this one pass 

will show up as just Bar instead of Foo.Bar.

(You'll still need to attach the __module__ to the qualname separately - __qualname__ is not intended to include module names.)

5 Comments

If you use github.com/wbolster/qualname you can get a qualname equivalent on older versions.
I.e. Type.__module__ + '.' + Type.__qualname__.
With Python 3.6, this only gives me the class name. It doesn't include the module.
@jpmc26 In Python 3.7, __qualname__ still only resolves to the class name
so what is the fix
35

Here's one based on Greg Bacon's excellent answer, but with a couple of extra checks:

__module__ can be None (according to the docs), and also for a type like str it can be __builtin__ (which you might not want appearing in logs or whatever). The following checks for both those possibilities:

def fullname(o): module = o.__class__.__module__ if module is None or module == str.__class__.__module__: return o.__class__.__name__ return module + '.' + o.__class__.__name__ 

(There might be a better way to check for __builtin__. The above just relies on the fact that str is always available, and its module is always __builtin__)

5 Comments

To save others the effort of comparing the two answers: the code in Greg Bacon's answer is now identical to the code in this one, other than that Greg added a pointless else statement and some code comments. MB is the real hero.
str.__class__.__module__ evaluates to 'builtins', so would there be anything wrong with if module is None or module == 'builtins'?
The docs say __module__ can be None for functions, but for classes, if Python can't determine a module when creating a type, the __module__ attribute just won't exist at all - you'll get an AttributeError if you try to access it. __module__ can also be manually set to arbitrary objects.
Checking module is None thus doesn't add any meaningful safety. Handling AttributeError and checking the type would be more useful, though still unlikely to matter.
Also, if you're that paranoid about __module__, you have to be equally paranoid about __class__, which is not actually guaranteed to be an object's class. It might not even be a class at all, for example if a class has a __getattribute__ override that doesn't special-case __class__.
32

For python3.7 I use:

".".join([obj.__module__, obj.__name__]) 

Getting:

package.subpackage.ClassName 

1 Comment

note that obj must be a class rather than an object instance.
22

Consider using the inspect module which has functions like getmodule which might be what are looking for:

>>>import inspect >>>import xml.etree.ElementTree >>>et = xml.etree.ElementTree.ElementTree() >>>inspect.getmodule(et) <module 'xml.etree.ElementTree' from 'D:\tools\python2.5.2\lib\xml\etree\ElementTree.pyc'> 

3 Comments

inspect.getmodule() returns module objects – not fully qualified class names. In fact, the inspect module provides no functionality whatsoever that would actually address this question. This answer is a non-answer. </facepalm>
Should be <facepalm/>
Helpful. Except for classes defined in the builtins module, the fully qualified name of a class might typically represent the class' module name suffixed with the cls.__name__, and now we have a function for determining if the class is defined in the builtins module, e.g that module returned by inspect.getmodule(object). Accessing the module class in itself might seem to be a bit more challenging, except by a similar indirection?
13

Some people (e.g. https://stackoverflow.com/a/16763814/5766934) arguing that __qualname__ is better than __name__. Here is an example that shows the difference:

$ cat dummy.py class One: class Two: pass $ python3.6 >>> import dummy >>> print(dummy.One) <class 'dummy.One'> >>> print(dummy.One.Two) <class 'dummy.One.Two'> >>> def full_name_with_name(klass): ... return f'{klass.__module__}.{klass.__name__}' >>> def full_name_with_qualname(klass): ... return f'{klass.__module__}.{klass.__qualname__}' >>> print(full_name_with_name(dummy.One)) # Correct dummy.One >>> print(full_name_with_name(dummy.One.Two)) # Wrong dummy.Two >>> print(full_name_with_qualname(dummy.One)) # Correct dummy.One >>> print(full_name_with_qualname(dummy.One.Two)) # Correct dummy.One.Two 

Note, it also works correctly for builtins:

>>> print(full_name_with_qualname(print)) builtins.print >>> import builtins >>> builtins.print <built-in function print> 

Comments

11

__module__ would do the trick.

Try:

>>> import re >>> print re.compile.__module__ re 

This site suggests that __package__ might work for Python 3.0; However, the examples given there won't work under my Python 2.5.2 console.

1 Comment

That does the trick, thanks! For the fully qualified name I will use "%s.%s" % (x.__class__.__module__, x.__class__.__name__)
7

This is a hack but I'm supporting 2.6 and just need something simple:

>>> from logging.handlers import MemoryHandler as MH >>> str(MH).split("'")[1] 'logging.handlers.MemoryHandler' 

1 Comment

This depends on the __repr__() implementation in the checked class (and on __str__() not being overriden). Useless in most cases.
5

Bellow is just an improvement of Greg Bacon's answer, tested for class, instance, method, function, both builtin and user defined.

def fullname(o): try: # if o is a class or function, get module directly module = o.__module__ except AttributeError: # then get module from o's class module = o.__class__.__module__ try: # if o is a class or function, get name directly name = o.__qualname__ except AttributeError: # then get o's class name name = o.__class__.__qualname__ # if o is a method of builtin class, then module will be None if module == 'builtins' or module is None: return name return module + '.' + name 

2 Comments

How can we get the full name of (global) variables and Properties?
@Piranna class and def record their name and module but for variables that's not generally possible. E.g. myvar = None, it's not even a fresh instance, there is no MAGIC(myvar) that could look at the None object and trace it back to specific module/variable you had in mind... Kludge: for unique values, gc.get_referrers() may find the module, and then you can iterate module's .__dict__ to find the name [it's slow; see more caveats in its doc]. But if you got the value without knowing wherefrom, you'll have >1 referers.
3

I'm using Python 3.12 because this is 2024. If you're still using Python 2, whoever is your boss, they deserve the pain. For those living in the XXI century, this has been doing it for me:

who = lambda obj: f'{obj.__class__.__module__}.{obj.__class__.__qualname__}' 

No need to call '.'.join() (much less make a list for it when a tuple does the same and is CHEAPER!) and there's this f-string thing, which is better than the % stuff by a landslide.

I've been using this in my own objects, so no edge cases where __module__ might be None, but I tried it against all sorts of things — including None! — and this simply works.

Comments

2

Since the interest of this topic is to get fully qualified names, here is a pitfall that occurs when using relative imports along with the main module existing in the same package. E.g., with the below module setup:

$ cat /tmp/fqname/foo/__init__.py $ cat /tmp/fqname/foo/bar.py from baz import Baz print Baz.__module__ $ cat /tmp/fqname/foo/baz.py class Baz: pass $ cat /tmp/fqname/main.py import foo.bar from foo.baz import Baz print Baz.__module__ $ cat /tmp/fqname/foo/hum.py import bar import foo.bar 

Here is the output showing the result of importing the same module differently:

$ export PYTHONPATH=/tmp/fqname $ python /tmp/fqname/main.py foo.baz foo.baz $ python /tmp/fqname/foo/bar.py baz $ python /tmp/fqname/foo/hum.py baz foo.baz 

When hum imports bar using relative path, bar sees Baz.__module__ as just "baz", but in the second import that uses full name, bar sees the same as "foo.baz".

If you are persisting the fully-qualified names somewhere, it is better to avoid relative imports for those classes.

2 Comments

The problem with this comment is it's getting confused due to the PYTHONPATH adjustments performed by direct script execution: when executing a .py file, Python will automatically add that file's directory on the path. So python /tmp/fqname/foo/bar.py has a pythonpath of /tmp/fqname/foo:/tmp/fqname, and the "import baz" resolves to an absolute import not a relative one.
Trying this out in Python 3 will fail, because implicit relative imports have stopped being a thing, so bar.py and hum.py either use from .baz and the direct execution fails, or they use import baz and main.py fails. For it to work in both cases, they have to use an actual absolute import (from foo.baz import Baz), which disambiguates the import, and precludes an unexpected absolute import of baz as a top-level package.
2

This is an adaption of the answers by Greg Bacon and MB to use the qualified class name. Note that the question did ask for the qualified class name. It was tested with Python 3.8.

def fullname(obj: object) -> str: """Return the full name of the given object using its module and qualified class names.""" # Ref: https://stackoverflow.com/a/66508248/ module_name, class_name = obj.__class__.__module__, obj.__class__.__qualname__ if module_name in (None, str.__class__.__module__): return class_name return module_name + "." + class_name 

Comments

1

My solution is:

def fullname(obj) -> str: if type(obj).__qualname__ != "type": # obj is instance return ".".join( [ obj.__class__.__module__, obj.__class__.__qualname__, ] ) # obj is not instance return ".".join([obj.__module__, obj.__qualname__]) # not instance >>> print(fullname(datetime)) "datetime.datetime" # instance >>> print(fullname(datetime.now()) "datetime.datetime" # instance >>> print(fullname(3)) "builtins.int" 

Comments

0

None of the answers here worked for me. In my case, I was using Python 2.7 and knew that I would only be working with newstyle object classes.

def get_qualified_python_name_from_class(model): c = model.__class__.__mro__[0] name = c.__module__ + "." + c.__name__ return name 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.