Получить полное имя класса объекта в 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>