Получить полное имя класса объекта в Python
для целей ведения журнала я хочу получить полное имя класса объекта Python. (С полной квалификацией я имею в виду имя класса, включая имя пакета и модуля.)
Я знаю, о x.__class__.__name__
, но есть ли простой способ получить пакет и модуль?
9 ответов:
С помощью следующей программы
#! /usr/bin/env python import foo def fullname(o): return o.__module__ + "." + o.__class__.__qualname__ bar = foo.Bar() print fullname(bar)
и
Bar
определяется какclass Bar(object): def __init__(self, v=42): self.val = v
выход
$ ./prog.py foo.Bar
предоставленные ответы не имеют дело с вложенными классами. Хотя он не доступен до Python 3.3 ( PEP 3155), вы действительно хотите использовать
__qualname__
класса. В конце концов (3.4? PEP 395),__qualname__
также будет существовать для модулей для обработки случаев, когда модуль переименован (т. е. когда он переименован в__main__
).
рассмотрите возможность использования
inspect
модуль, который имеет такие функции, какgetmodule
который может быть то, что вы ищете:>>>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'>
вот один из них, основанный на отличном ответе Грега Бэкона, но с парой дополнительных проверок:
__module__
может бытьNone
(согласно документам), а также для типа типаstr
может быть__builtin__
(который вы, возможно, не хотите появляться в журналах или что-то еще). Следующие проверки для обеих этих возможностей: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__
(возможно, есть лучший способ проверить
__builtin__
. Вышесказанное просто опирается на то, что str всегда доступен, и его модуль всегда__builtin__
)
__module__
будет делать трюк.попробуй:
>>> import re >>> print re.compile.__module__ re
этот сайт говорит о том, что
__package__
может работать для Python 3.0; однако приведенные там примеры не будут работать под моей консолью Python 2.5.2.
это хак, но я поддерживаю 2.6 и просто нужно что-то простое:
>>> from logging.handlers import MemoryHandler as MH >>> str(MH).split("'")[1] 'logging.handlers.MemoryHandler'
поскольку интерес этой темы заключается в том, чтобы получить полные имена, вот ловушка, которая возникает при использовании относительного импорта вместе с основным модулем, существующим в том же пакете. Например, с помощью приведенной ниже настройки модуля:
$ 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
вот вывод, показывающий результат импорта одного и того же модуля по-разному:
$ 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
когда hum импортирует бар, используя относительный путь, бар видит
Baz.__module__
Как только "baz", но во втором импорте, который использует полное имя, бар видит то же самое как "Фу.baz."Если вы где-то сохраняете полные имена, лучше избегать относительного импорта для этих классов.
ни один из ответов здесь работал для меня. В моем случае я использовал Python 2.7 и знал, что буду работать только с newstyle
object
классы.def get_qualified_python_name_from_class(model): c = model.__class__.__mro__[0] name = c.__module__ + "." + c.__name__ return name
некоторые люди (например https://stackoverflow.com/a/16763814/5766934) аргументируя это
__qualname__
лучше, чем__name__
. Вот пример, который показывает разницу:$ 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
заметьте, он также работает правильно для buildins:
>>> print(full_name_with_qualname(print)) builtins.print >>> import builtins >>> builtins.print <built-in function print>