获取Python中对象的完全限定类名
出于日志记录的目的,我想检索Python对象的完全限定类名。(对于完全限定,我指的是类名,包括包和模块名。)获取Python中对象的完全限定类名,python,python-datamodel,Python,Python Datamodel,出于日志记录的目的,我想检索Python对象的完全限定类名。(对于完全限定,我指的是类名,包括包和模块名。) 我知道x.\uuuuu class\uuuuu.\uuuuu name\uuuuuuu,但是有没有一个简单的方法来获取包和模块?\uuuuu模块就可以了 尝试: 建议\uuuuuuuuuuuuuuuuuuuuuuuu可能适用于Python 3.0;但是,这里给出的示例在我的Python 2.5.2控制台下不起作用。考虑使用inspect模块,该模块具有类似getmodule的功能,这可能
我知道
x.\uuuuu class\uuuuu.\uuuuu name\uuuuuuu
,但是有没有一个简单的方法来获取包和模块?\uuuuu模块
就可以了
尝试:
建议
\uuuuuuuuuuuuuuuuuuuuuuuu
可能适用于Python 3.0;但是,这里给出的示例在我的Python 2.5.2控制台下不起作用。考虑使用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'>
导入检查
>>>导入xml.etree.ElementTree
>>>et=xml.etree.ElementTree.ElementTree()
>>>检查。获取模块(et)
使用以下程序
#/usr/bin/env python
进口食品
def全名(o):
klass=o.\u类__
模块=klass.\uu模块__
如果模块==‘内置’:
返回klass.uuu qualname_u35;避免像'builtins.str'这样的输出
返回模块+'.+klass.\uuu qualname__
bar=foo.bar()
打印(全名(条形))
和Bar
定义为
类栏(对象):
定义初始化(self,v=42):
self.val=v
输出是
$ ./prog.py
foo.Bar
如果您仍然停留在Python2上,您将不得不使用\uuuu name\uuuuuuu
而不是\uuuuu qualname\uuuuu
,这对于嵌套类来说信息较少-嵌套在类Foo
中的类Bar
将显示为Bar
,而不是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__
由于本主题的目的是获取完全限定名,因此在使用相对导入以及同一包中存在的主模块时,会出现一个陷阱。例如,使用以下模块设置:
$ 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使用相对路径导入bar时,bar会将Baz.\uuuuu模块\uuuu
视为“Baz”,但在使用全名的第二次导入中,bar会将其视为“foo.Baz”
如果要在某个地方持久化完全限定名,最好避免这些类的相对导入。以下是一个基于Greg Bacon出色答案的示例,但需要进行一些额外检查:
模块可以是无
(根据文档),对于像str
这样的类型,它也可以是内置的(您可能不希望出现在日志或其他文件中)。以下检查这两种可能性:
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__
(可能有更好的方法来检查\uuuuuuuuuuuuuuuuuuuuuuuuuuuu
。以上只是依赖于str总是可用的事实,它的模块总是\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
)提供的答案不处理嵌套类。虽然直到Python3.3()才可用,但您确实希望使用类的\uuuuuu qualname\uuuu
,而不是\uuu name\uuuu
。否则,像
class Foo:
class Bar: # this one
pass
将仅显示为Bar
,而不是Foo.Bar
(您仍然需要将\uuuu模块
单独附加到qualname上-\uuuu qualname
并不打算包含模块名称。)这是一个黑客攻击,但我支持2.6,只需要一些简单的东西:
>>> from logging.handlers import MemoryHandler as MH
>>> str(MH).split("'")[1]
'logging.handlers.MemoryHandler'
这里没有一个答案对我有用。在我的例子中,我使用的是Python2.7,并且知道我将只使用newstyleobject
类
def get_qualified_python_name_from_class(model):
c = model.__class__.__mro__[0]
name = c.__module__ + "." + c.__name__
return name
一些人(例如)认为\uuuuu qualname\uuu
比\uu name\uuuu
好。
下面是一个显示差异的示例:
$ 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
$cat dummy.py
第一类:
第二类:
通过
$python3.6
>>>导入虚拟
>>>打印(虚拟1)
>>>打印(虚拟1.2)
>>>def全名带全名(klass):
... 返回f'{klass.\uuuuu模块{klass.\uuuuu名称}'
>>>def全名(klass):
... 返回f'{klass.\uuuuuu模块{klass.\uuuuuqalname.\uuuu}'
>>>打印(全名加上全名(dummy.One))#正确
笨蛋,一个
>>>打印(全名加上全名(dummy.1.2))#错误
笨蛋,两个
>>>打印(全名加上全名(dummy.One))#正确
笨蛋,一个
>>>打印(全名和相等名(dummy.1.2))#正确
一,二
注意,它也适用于内置:
>>> print(full_name_with_qualname(print))
builtins.print
>>> import builtins
>>> builtins.print
<built-in function print>
>>打印(全名加上全名(打印))
内置打印
>>>进口内置设备
>>>内置打印
对于python3.7,我使用:
“.join([obj.\uuuuuu模块,obj.\uuuuu名称])
获取:
package.subpackage.ClassName
这是由和改编的答案,以使用限定的类名。请注意,该问题确实要求使用限定的类名。它是用Python3.8测试的
def fullname(obj:object)->str:
“”“使用给定对象的模块名和限定类名返回该对象的全名。”“”
#参考:https://stackoverflow.com/a/66508248/
模块名称,类名称=对象。\类名称。\模块名称,对象。\类名称。\质量名称__
如果模块名称在(无,str.\uuuuuuu类\uuuuuuu.\uuuuuu模块\uuuuuuu):
返回类名称
返回模块名称+“+”类名称
这就成功了,谢谢!对于完全限定名称,我将使用“%s.%s”%(x.\uuuuuu class\uuuuuu.\uuuuuu模块,x.\uuuuuu class\uuuuuuu.\uuuuuu name\uuuuuuuuuuu)
这似乎返回定义了条的模块,而不是定义了条的模块。如果日志记录的目的是确切地知道它是什么类型的对象,那么这似乎没有帮助。是o.\uuuu class\uuuu.\uuuu module\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
对于Python3Doesn有时不起作用:AttributeError:“AttributeError”对象没有属性“\uu模块”
如果使用,则可以在旧版本上获得等效的qualname<代码>类型。_u模块_+'.+Type._u质量名称_
。在Python3.6中,这只提供类名。它不包括模块。@jpmc26在Python 3.7中,\uuuuuqalname\uuuq
仍然只解析为类名inspect.getmodule()package.subpackage.ClassName