在Python中获取对象的全限定名称
为了logging目的,我想检索一个Python对象的全限定类名。 (完全合格的我的意思是类名,包括包和模块名称。)
我知道x.__class__.__name__
,但有一个简单的方法来获取包和模块?
用下面的程序
#! /usr/bin/env python import foo def fullname(o): return o.__module__ + "." + o.__class__.__name__ bar = foo.Bar() print fullname(bar)
和Bar
定义为
class Bar(object): def __init__(self, v=42): self.val = v
输出是
$ ./prog.py foo.Bar
考虑使用具有getmodule
function的inspect
模块,它可能是寻找的东西:
>>>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'>
提供的答案不处理嵌套的类。 虽然在Python 3.3( PEP 3155 )之前它不可用,但是你真的想使用类的__qualname__
。 最后(3.4? PEP 395 ), __qualname__
也会存在,用于处理模块重命名(即重命名为__main__
)的情况。
这里有一个基于Greg Bacon的出色答案,但是还有一些额外的检查:
__module__
可以是None
(根据文档),也可以是像str
这样的types,它可以是__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
这个网站build议__package__
可能适用于Python 3.0; 但是,这里给出的例子在我的Python 2.5.2控制台下不起作用。
这是一个黑客,但我支持2.6,只需要一些简单的:
>>> from logging.handlers import MemoryHandler as MH >>> str(MH).split("'")[1] 'logging.handlers.MemoryHandler'
由于本主题的兴趣是获取完全限定名称,因此在使用相对导入function以及相同包中的主模块时,会出现一个错误。 例如:
$ mkdir -p /tmp/fqname/foo $ touch /tmp/fqname/foo/__init__.py $ cat<<END > /tmp/fqname/foo/bar.py > from baz import Baz > print Baz.__module__ > END $ cat<<END > /tmp/fqname/foo/baz.py > class Baz: pass > END $ cat <<END > /tmp/fqname/main.py > import foo.bar > from foo.baz import Baz > print Baz.__module__ > END $ cat <<END > /tmp/fqname/foo/hum.py > import bar > import foo.bar > END $ PYTHONPATH=/tmp/fqname python /tmp/fqname/main.py foo.baz foo.baz $ PYTHONPATH=/tmp/fqname python /tmp/fqname/foo/bar.py baz $ PYTHONPATH=/tmp/fqname python /tmp/fqname/foo/hum.py baz foo.baz
当嗡嗡声使用相对path导入栏时,bar将Baz.__module__
看作是“baz”,但在使用全名的第二个导入中,bar看起来与“foo.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