154

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?

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Hanno S.
  • 2,631
  • 3
  • 17
  • 27

11 Answers11

168

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__
user2357112 supports Monica
  • 215,440
  • 22
  • 321
  • 400
Greg Bacon
  • 121,231
  • 29
  • 179
  • 236
45

The provided answers don't deal with nested classes. Though it's not available until Python 3.3 (PEP 3155), you really want to use the __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.)

user2357112 supports Monica
  • 215,440
  • 22
  • 321
  • 400
Nathan Binkert
  • 8,088
  • 1
  • 26
  • 37
22

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__)

MB.
  • 6,959
  • 6
  • 38
  • 42
  • 4
    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. – MarredCheese Sep 22 '19 at 03:40
  • `str.__class__.__module__` evaluates to `'builtins'`, so would there be anything wrong with `if module is None or module == 'builtins'`? – ChrisCrossCrash Feb 12 '21 at 14:34
  • 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. – user2357112 supports Monica Apr 10 '21 at 08:38
  • 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. – user2357112 supports Monica Apr 10 '21 at 08:41
  • 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__`. – user2357112 supports Monica Apr 10 '21 at 09:00
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'>
Tendayi Mawushe
  • 24,137
  • 5
  • 45
  • 56
  • 12
    `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. `` – Cecil Curry Jan 03 '19 at 06:05
16

For python3.7 I use:

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

Getting:

package.subpackage.ClassName
Prisacari Dmitrii
  • 1,377
  • 15
  • 27
8

__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.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Adam Matan
  • 107,447
  • 124
  • 346
  • 512
  • 6
    That does the trick, thanks! For the fully qualified name I will use `"%s.%s" % (x.__class__.__module__, x.__class__.__name__)` – Hanno S. Jan 07 '10 at 12:06
8

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>
Acumenus
  • 41,481
  • 14
  • 116
  • 107
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'
Gringo Suave
  • 25,443
  • 6
  • 77
  • 69
  • 2
    This depends on the `__repr__()` implementation in the checked class (**and** on `__str__()` not being overriden). Useless in most cases. – z33k Aug 07 '19 at 17:40
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.

haridsv
  • 7,212
  • 4
  • 56
  • 57
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
Myer
  • 3,434
  • 1
  • 34
  • 46
0

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

Acumenus
  • 41,481
  • 14
  • 116
  • 107