पायथन में किसी वस्तु का पूरी तरह से योग्य वर्ग नाम प्राप्त करें


136

लॉगिंग उद्देश्यों के लिए मैं पायथन ऑब्जेक्ट के पूरी तरह से योग्य वर्ग नाम को पुनः प्राप्त करना चाहता हूं। (पूरी तरह से योग्य के साथ मेरा मतलब है कि पैकेज और मॉड्यूल नाम सहित वर्ग का नाम।)

मुझे पता है x.__class__.__name__, लेकिन क्या पैकेज और मॉड्यूल प्राप्त करने के लिए एक सरल विधि है?

जवाबों:


147

निम्नलिखित कार्यक्रम के साथ

#! /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

2
यह मॉड्यूल को वापस करने के लिए प्रकट होता है जहां बार को परिभाषित किया गया था, न कि जहां बार को परिभाषित किया गया था। यदि लॉगिंग का उद्देश्य वास्तव में यह जानना है कि यह किस प्रकार का ऑब्जेक्ट था, तो यह मदद करने के लिए प्रतीत नहीं होता है।
मार्क ई। हासे

क्या o.__class__.__module__कभी इससे अलग है o.__module__?
19

2
लार्क्स: हाँ यह है, stackoverflow.com/questions/5271112/…
यारोस्लाव Bulatov

1
मैं दृढ़ता से ".".join([o.__module__, o.__name__])Python3
Piotr P Novczek

कभी-कभी काम नहीं करता:AttributeError: 'AttributeError' object has no attribute '__module__'
हेंडी इरावन

38

प्रदान किए गए उत्तर नेस्टेड कक्षाओं के साथ सौदा नहीं करते हैं। हालाँकि यह Python 3.3 ( PEP 3155 ) तक उपलब्ध नहीं है , आप वास्तव __qualname__में क्लास का उपयोग करना चाहते हैं । आखिरकार (3.4? PEP 395 ), __qualname__मॉड्यूल के लिए उन मामलों से निपटने के लिए भी मौजूद होगा , जहां मॉड्यूल का नाम बदला गया है (यानी जब इसका नाम बदला गया है __main__)।


3
आप का उपयोग करते हैं github.com/wbolster/qualname आप एक प्राप्त कर सकते हैं qualname पुराने संस्करणों पर बराबर।
राउटर बोलस्टरली

3
Ie Type.__module__ + '.' + Type.__qualname__
केंटो

4
पायथन 3.6 के साथ, यह केवल मुझे कक्षा का नाम देता है। इसमें मॉड्यूल शामिल नहीं है।
jpmc26

2
@ jpmc26 Python 3.7 में, __qualname__अभी भी केवल वर्ग के नाम पर हल होता है
zepp.lee

22

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'>

7
inspect.getmodule()मॉड्यूल ऑब्जेक्ट लौटाता है - पूरी तरह से योग्य वर्ग नाम नहीं। वास्तव में, inspectमॉड्यूल कोई भी कार्यक्षमता प्रदान नहीं करता है जो वास्तव में इस प्रश्न को संबोधित करेगा। यह उत्तर एक गैर-उत्तर है। </facepalm>
सेसिल करी

19

यहाँ एक ग्रेग बेकन के उत्कृष्ट उत्तर पर आधारित है, लेकिन कुछ अतिरिक्त जाँचों के साथ:

__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__)


2
दो जवाबों की तुलना करने के प्रयास से दूसरों को बचाने के लिए: ग्रेग बेकन के जवाब में कोड अब इस एक के कोड के समान है, इसके अलावा ग्रेग ने एक व्यर्थ बयान और कुछ कोड टिप्पणियों को जोड़ा। एमबी असली हीरो है।
MarredCheese


9

__module__ चालबाजी करेगा।

प्रयत्न:

>>> import re
>>> print re.compile.__module__
re

यह साइट बताती है कि __package__अजगर 3.0 के लिए काम कर सकता है; हालाँकि, दिए गए उदाहरण मेरे पायथन 2.5.2 कंसोल के तहत काम नहीं करेंगे।


6
यह चाल है, धन्यवाद! पूरी तरह से योग्य नाम के लिए"%s.%s" % (x.__class__.__module__, x.__class__.__name__)
हन्नो एस।

7

यह एक हैक है, लेकिन मैं 2.6 का समर्थन कर रहा हूं और बस कुछ आसान चाहिए:

>>> from logging.handlers import MemoryHandler as MH
>>> str(MH).split("'")[1]

'logging.handlers.MemoryHandler'

1
यह __repr__()चेक किए गए वर्ग में कार्यान्वयन पर निर्भर करता है ( और अधिक__str__() नहीं होने पर )। ज्यादातर मामलों में बेकार।
z33k

7

कुछ लोग (जैसे 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

ध्यान दें, बिल्डरों के लिए भी यह सही ढंग से काम करता है:

>>> print(full_name_with_qualname(print))
builtins.print
>>> import builtins
>>> builtins.print
<built-in function print>

2

चूंकि इस विषय की रुचि पूरी तरह से योग्य नामों को प्राप्त करने के लिए है, इसलिए यहां एक नुकसान है जो एक ही पैकेज में मौजूद मुख्य मॉड्यूल के साथ रिश्तेदार आयात का उपयोग करते समय होता है। उदाहरण के लिए, नीचे मॉड्यूल सेटअप के साथ:

$ 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__सिर्फ "बाज" के रूप में देखता है, लेकिन दूसरे आयात में जो पूर्ण नाम का उपयोग करता है, बार "foo.baz" के रूप में देखता है।

यदि आप कहीं पूरी तरह से योग्य नामों को जारी रख रहे हैं, तो उन वर्गों के लिए सापेक्ष आयात से बचना बेहतर है।


0

यहां किसी भी जवाब ने मेरे लिए काम नहीं किया। मेरे मामले में, मैं पायथन 2.7 का उपयोग कर रहा था और जानता था कि मैं केवल न्यूस्टाइल objectकक्षाओं के साथ काम करूंगा ।

def get_qualified_python_name_from_class(model):
    c = model.__class__.__mro__[0]
    name = c.__module__ + "." + c.__name__
    return name
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.