获取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的功能,这可能

出于日志记录的目的,我想检索Python对象的完全限定类名。(对于完全限定,我指的是类名,包括包和模块名。)


我知道
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,并且知道我将只使用newstyle
object

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