পাইথনে কোনও সামগ্রীর পুরোপুরি যোগ্যতাসম্পন্ন শ্রেণীর নাম পান


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

2
larsks: হ্যা এটাই stackoverflow.com/questions/5271112/...
Yaroslav Bulatov

1
আমি ".".join([o.__module__, o.__name__])দৃ strongly়রূপে পাইথন 3
পিয়োটার পেকজেক

কখনও কখনও কাজ করে না:AttributeError: 'AttributeError' object has no attribute '__module__'
হেন্ডি ইরাওয়ান

38

প্রদত্ত উত্তরগুলি নেস্টেড ক্লাসগুলির সাথে কাজ করে না। যদিও পাইথন ৩.৩ ( পিইপি ৩১৫৫ ) অবধি এটি উপলভ্য নয় , আপনি সত্যিই __qualname__ক্লাসটি ব্যবহার করতে চান । অবশেষে (3.4? পিইপি 395 ), __qualname__মডিউলগুলির ক্ষেত্রে মডিউলটির নতুন নামকরণ (যেমন এটি পুনরায় নামকরণ করা হয় __main__) ক্ষেত্রে মোকাবেলা করার জন্যও উপস্থিত থাকবে ।


3
আপনি যদি github.com/wbolster/qualname ব্যবহার করেন তবে পুরানো সংস্করণগুলিতে আপনি একটি যোগ্যতার সমতুল্য পেতে পারেন ।
ওয়াউটার বলস্টারলি

3
অর্থাৎ Type.__module__ + '.' + Type.__qualname__
কেনটজো

4
পাইথন ৩.6 সহ, এটি কেবল আমাকে ক্লাসের নাম দেয়। এটি মডিউলটি অন্তর্ভুক্ত করে না।
jpmc26

2
@ jpmc26 পাইথন ৩.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মডিউলটি কোনও কার্যকারিতা সরবরাহ করে না যা আসলে এই প্রশ্নের সমাধান করবে address এই উত্তর একটি উত্তর নেই। </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__The উপরেরটি কেবল স্ট্র সর্বদা উপলভ্য এবং এইটির মডিউলটি সর্বদা পাওয়া যায় তার উপর নির্ভর করে __builtin__)


1
দুটি জবাবের তুলনা করার প্রচেষ্টা অন্যকে বাঁচাতে: গ্রেগ ব্যাকনের উত্তরের কোডটি এখন এই উত্তরটির কোডের সাথে একই, গ্রেগ ব্যতীত অন্য কোনও বিবৃতি এবং কিছু কোড মন্তব্য যুক্ত করেছে। এমবি আসল নায়ক।
মারেডচিজ


9

__module__ কৌতুক করবে।

চেষ্টা করুন:

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

এই সাইটটি প্রস্তাব দেয় যে __package__পাইথন 3.0 এর জন্য কাজ করতে পারে; তবে সেখানে দেওয়া উদাহরণগুলি আমার পাইথন ২.২.২ কনসোলের আওতায় কাজ করবে না।


6
কৌতুকটি করে, ধন্যবাদ! সম্পূর্ণরূপে যোগ্য নামের জন্য আমি ব্যবহার করব "%s.%s" % (x.__class__.__module__, x.__class__.__name__)
হ্যানো এস

7

এটি একটি হ্যাক তবে আমি ২.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.বাজ" হিসাবে দেখতে পায়।

আপনি যদি কোথাও পুরোপুরি যোগ্যতাসম্পন্ন নামগুলি চালিয়ে যাচ্ছেন তবে এই শ্রেণীর জন্য আপেক্ষিক আমদানি এড়ানো ভাল।


0

এখানে উত্তরগুলির কোনওটিই আমার পক্ষে কার্যকর হয়নি। আমার ক্ষেত্রে, আমি পাইথন ২.7 ব্যবহার করছিলাম এবং জানতাম যে আমি কেবল নিউস্টাইল objectক্লাস নিয়ে কাজ করব ।

def get_qualified_python_name_from_class(model):
    c = model.__class__.__mro__[0]
    name = c.__module__ + "." + c.__name__
    return name
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.