Pythonでオブジェクトの完全修飾クラス名を取得します。
-
19-09-2019 - |
質問
ログ記録の目的のために私はPythonオブジェクトの完全修飾クラス名を取得します。 (完全修飾で、私はパッケージとモジュール名を含むクラス名を意味します。)
私はx.__class__.__name__
について知っているが、パッケージやモジュールを取得するための簡単な方法はありますか?
解決
次のプログラムでは、
#! /usr/bin/env python
import foo
def fullname(o):
# o.__module__ + "." + o.__class__.__qualname__ is an example in
# this context of H.L. Mencken's "neat, plausible, and wrong."
# Python makes no guarantees as to whether the __module__ special
# attribute is defined, so we take a more circumspect approach.
# Alas, the module name is explicitly excluded from __qualname__
# in Python 3.
module = o.__class__.__module__
if module is None or module == str.__class__.__module__:
return o.__class__.__name__ # Avoid reporting __builtin__
else:
return 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
他のヒント
のために何を求めているかもしれない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
これはハックですが、私は2.6をサポートしていることだし、単純な何かを必要とします:
>>> from logging.handlers import MemoryHandler as MH
>>> str(MH).split("'")[1]
'logging.handlers.MemoryHandler'
一部の人(例えば 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>
python3.7のために私が使用します:
".".join([obj.__module__, obj.__name__])
入手ます:
package.subpackage.ClassName
、ここでは同じパッケージ内の既存のメインモジュールと一緒に相対的な輸入品を使用した場合に発生する落とし穴があります。例えば、以下のモジュールをセットアップしてます:
$ 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
相対パスを使用したハムの輸入バーは、バーは単に「バズ」としてBaz.__module__
見ているが、完全な名前を使用する第2のインポートでは、バーは「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