2017-06-30 13 views
20

एक पायथन प्रोग्राम में, यदि प्रोग्राम के नामस्थान में कोई नाम मौजूद है, तो यह पता लगाना संभव है कि नाम कुछ मॉड्यूल से आयात किया गया है, और यदि हां, तो कौन सा मॉड्यूल आयात किया जाता है?मैं कैसे पता लगा सकता हूं कि कौन सा मॉड्यूल नाम से आयात किया जाता है?

उत्तर

21

आप जो मॉड्यूल एक समारोह __module__ विशेषता के माध्यम से में परिभाषित किया गया है देख सकते हैं । From the Python Data model documentation on __module__:

मॉड्यूल का नाम परिभाषित किया गया था, या अनुपलब्ध होने पर कोई भी नहीं।

उदाहरण:

>>> from re import compile 
>>> compile.__module__ 
're' 
>>> def foo(): 
...  pass 
... 
>>> foo.__module__ 
'__main__' 
>>> 

The Data model later mentions कि वर्गों के साथ-साथ एक ही विशेषता है:

__module__ मॉड्यूल का नाम है, जिसमें वर्ग परिभाषित किया गया है।

>>> from datetime import datetime 
>>> datetime.__module__ 
'datetime' 
>>> class Foo: 
...  pass 
... 
>>> Foo.__module__ 
'__main__' 
>>> 

आप भी इस तरह के int और list के रूप में निर्मित नाम के साथ ऐसा कर सकते हैं। आप उन्हें builtins मॉड्यूल से एक्सेस कर सकते हैं।

>>> int.__module__ 
'builtins' 
>>> list.__module__ 
'builtins' 
>>> 

मैं from builtins import int, list बिना int और list उपयोग कर सकते हैं। तो int और list मेरे प्रोग्राम में कैसे उपलब्ध हो?

ऐसा इसलिए है क्योंकि int और list अंतर्निहित नाम हैं। आपको वर्तमान नामस्थान में उन्हें खोजने में सक्षम होने के लिए उन्हें पायथन के लिए स्पष्ट रूप से आयात करने की आवश्यकता नहीं है। आप इसे CPython virtual machine source code में अपने लिए देख सकते हैं। जैसा कि @ user2357112 उल्लेख किया गया है, वैश्विक लुकअप विफल होने पर अंतर्निहित नामों का उपयोग किया जाता है। यहां प्रासंगिक स्निपेट है:

if (v == NULL) { 
    v = PyDict_GetItem(f->f_globals, name); 
    Py_XINCREF(v); 
    if (v == NULL) { 
     if (PyDict_CheckExact(f->f_builtins)) { 
      v = PyDict_GetItem(f->f_builtins, name); 
      if (v == NULL) { 
       format_exc_check_arg(
          PyExc_NameError, 
          NAME_ERROR_MSG, name); 
       goto error; 
      } 
      Py_INCREF(v); 
     } 
     else { 
      v = PyObject_GetItem(f->f_builtins, name); 
      if (v == NULL) { 
       if (PyErr_ExceptionMatches(PyExc_KeyError)) 
        format_exc_check_arg(
           PyExc_NameError, 
           NAME_ERROR_MSG, name); 
       goto error; 
      } 
     } 
    } 
} 

उपरोक्त कोड में, सीपीथन पहले वैश्विक दायरे में एक नाम की खोज करता है। यदि यह विफल हो जाता है, तो यह वापस आ जाता है और मौजूदा फ्रेम ऑब्जेक्ट में इसके निष्पादन में बिल्टिन नामों के मैपिंग से नाम प्राप्त करने का प्रयास करता है। यही f->f_builtins है।

आप sys._getframe() का उपयोग कर अजगर स्तर से इस मानचित्रण का निरीक्षण कर सकते हैं:

>>> import sys 
>>> frame = sys._getframe() 
>>> 
>>> frame.f_builtins['int'] 
<class 'int'> 
>>> frame.f_builtins['list'] 
<class 'list'> 
>>> 

sys._getframe() कॉल स्टैक के शीर्ष पर फ़्रेम लौटाता है। इस मामले में, यह मॉड्यूल स्कोप के लिए फ्रेम है।और जैसा कि आप ऊपर से देख सकते हैं, f_builtins फ्रेम के लिए मैपिंग में int और list कक्षाएं हैं, इसलिए पायथन ने स्वचालित रूप से उन नामों को आपके लिए उपलब्ध कराया है। दूसरे शब्दों में, यह उन्हें "निर्मित" क्षेत्र में बनाया गया है; इसलिए शब्द "बिल्टिन"

+0

धन्यवाद। क्या यह संभव है यह जानने के लिए कि 'int' और' list' जैसे बिल्टिन प्रकारों को कौन सा मॉड्यूल आयात किया गया है? – Tim

+0

@ टिम यूप से आयात करें। अपने आरईपीएल में 'int .__ मॉड्यूल__' और' list .__ मॉड्यूल__' 'आज़माएं।' बिल्टिन 'मॉड्यूल में परिभाषित किया गया है –

+0

मैं 'int' और' list' का उपयोग 'अंतर्निहित आयात int, सूची' से 'के बिना कर सकता हूं। तो मेरे प्रोग्राम में' int' और 'list' कैसे उपलब्ध हो सकता है? – Tim

5

कुछ ऑब्जेक्ट्स (लेकिन सभी से दूर) में __module__ विशेषता है।

5

जब तक कोड वैश्विक अद्यतन करने की तरह कुछ असामान्य कर रहा है सीधे, स्रोत कोड का संकेत देना चाहिए जहां हर चर से आया था:

x = 10       # Assigned in the current module 
from random import randrange # Loaded from random 
from functools import *  # Loads everything listed in functools.__all__ 
+0

धन्यवाद। यदि आपके स्रोत कोड में 'आयात *' से कई आयात विवरण हैं, तो आप कैसे बता सकते हैं कि कौन सा मॉड्यूल एक चर से आता है? – Tim

+0

"somemod import ** स्टेटमेंट्स से सभी मॉड्यूल से पता चलता है कि कौन से मॉड्यूल से आया था। हालांकि, आप आयात के अलावा अपना खुद का" आयात somemod "चला सकते हैं और ऊपर सूचीबद्ध के रूप में आगे बढ़ सकते हैं। –

6

किसी कारण स्रोत अनुपलब्ध है के लिए, आप inspect से getmodule इस्तेमाल कर सकते हैं, तो जो __module__ हथियाने यदि वह मौजूद है और उसके बाद अन्य विकल्पों पर वापस गिरने से मॉड्यूल को खोजने के लिए अपने सबसे अच्छे रूप कोशिश करता है।

यदि सबकुछ ओ.के. हो जाता है, तो आप मॉड्यूल ऑब्जेक्ट वापस लेते हैं। कि से, आप __name__ हड़पने मॉड्यूल का वास्तविक नाम पाने के लिए कर सकते हैं:

from inspect import getmodule 
from collections import OrderedDict 
from math import sin  

getmodule(getmodule).__name__ 
'inspect' 
getmodule(OrderedDict).__name__ 
'collections' 
getmodule(sin).__name__ 
'math' 

यह कुछ भी नहीं मिल रहा है, तो यह रिटर्न None तो आप विशेष मामला इस करना होगा। आम तौर पर यह आपके लिए तर्क को समाहित करता है, इसलिए यदि आप मौजूद हैं तो __module__ को वास्तव में पकड़ने के लिए आपको स्वयं को एक फ़ंक्शन लिखने की आवश्यकता नहीं है।

यह उन वस्तुओं के लिए काम नहीं करता है जिनके पास यह जानकारी संलग्न नहीं है। तुम्हें पता है, फ़ॉल-बैक के रूप में, कोशिश करते हैं और प्रकार में पारित यह नाकाम करने के लिए कर सकते हैं:

o = OrderedDict() 
getmodule(o)    # None 
getmodule(type(0)).__name__ # 'collections' 

लेकिन वह हमेशा सही परिणाम नहीं होगा:

from math import pi 
getmodule(type(pi)).__name__ 
'builtins' 
4

तुम भी globals() देख सकते हैं , यह नामों के अंदर घोषित वैरिएबल, मॉड्यूल और फ़ंक्शंस के साथ-साथ सभी नामों के साथ एक ध्रुव आउटपुट करेगा। मॉड्यूल के साथ भी

if globals()['x']: 
    print('x exist') 

try: 
    print(globals()['y']) 
except KeyError: 
    print('but y does not') 

# x exist 
# but y does not 

काम करता है::

>>> x = 10 
>>> import os 
>>> globals() # to big to display here but finish with 
# {... 'x': 10, 'os': <module 'os' from '/usr/local/lib/python2.7/os.py'>} 

इसलिए, आप परीक्षण कर सकते हैं, तो चर इस तरह घोषित किया गया

print(globals()['os']) # <module 'os' from '/usr/local/lib/python2.7/os.py'> 

try: 
    print(globals()['math']) 
except KeyError: 
    print('but math is not imported') 

# <module 'os' from '/usr/local/lib/python2.7/os.py'> 
# but math is not imported 
+0

धन्यवाद। आप 'ग्लोबल्स()' के बजाय 'प्रिंट (ग्लोबल्स()) 'का उपयोग क्यों करते हैं? – Tim

+0

मैं परीक्षण करते समय एक पायथन कंसोल का उपयोग नहीं कर रहा हूं, इसलिए मुझे 'प्रिंट' की आवश्यकता है, लेकिन अगर आप अपनी पठनीयता को कम करते हैं तो मैं इसे हटा सकता हूं। –

संबंधित मुद्दे

 संबंधित मुद्दे