2008-10-17 23 views
42

__import__ का उपयोग बिंदीदार नाम के साथ करते समय, somepackage.somemodule, मॉड्यूल लौटाया गया somemodule नहीं है, जो कुछ भी लौटाया जाता है वह अधिकतर खाली लगता है! यहाँ क्या चल रहा है?पायथन का __import__ अपेक्षित काम नहीं करता है

उत्तर

52

अजगर डॉक्स से पर __import__:

__import__(name[, globals[, locals[, fromlist[, level]]]]) 

...

जब नाम चर प्रपत्र package.module की है, आम तौर पर, शीर्ष स्तर के पैकेज (नाम पहला डॉट तक) नाम दिया गया है, नाम से नामित मॉड्यूल नहीं। हालांकि, जब गैर-खाली सूची तर्क दिया जाता है, नाम से नामित मॉड्यूल वापस कर दिया जाता है। यह विभिन्न प्रकार के आयात विवरण के लिए उत्पन्न बाइटकोड के साथ संगतता के लिए किया जाता है; "आयात spam.ham.eggs" का उपयोग करते समय, शीर्ष-स्तरीय पैकेज स्पैम को आयात नामस्थान में रखा जाना चाहिए, लेकिन जब "स्पैम.हम आयात अंडे से" का उपयोग करके स्पैम.हम उप-पैकेज का उपयोग किया जाना चाहिए पर अंडे परिवर्तनीय खोजें। इस व्यवहार के लिए वर्कअराउंड के रूप में, इच्छित घटकों को निकालने के लिए getattr() का उपयोग करें। उदाहरण के लिए, आप निर्धारित कर सकते हैं निम्नलिखित सहायक:

def my_import(name): 
    mod = __import__(name) 
    components = name.split('.') 
    for comp in components[1:]: 
     mod = getattr(mod, comp) 
    return mod 

व्याख्या करने के लिए:

जब आप somepackage.somemodule, __import__ रिटर्न somepackage.__init__.py है, जो अक्सर खाली है के लिए पूछना।

यह somemodule वापसी अगर आप fromlist (आप चाहते हैं somemodule अंदर चर नाम, जो वास्तव में वापस नहीं कर रहे हैं की एक सूची)

तुम भी, जैसा कि मैंने किया था, समारोह वे सुझाव देते हैं उपयोग कर सकते हैं प्रदान करेगा।

नोट: मैंने इस प्रश्न को पूरी तरह उत्तर देने का इरादा से पूछा। मेरे कोड में एक बड़ी बग थी, और इसे गलत तरीके से पहचानने के बाद, मुझे इसे समझने में काफी समय लगा, इसलिए मुझे लगा कि मैं एसओ समुदाय को बाहर करने में मदद करता हूं और गॉचा पोस्ट करता हूं, मैं यहां भाग गया। twisted.python.reflect.namedAny:

7

वहाँ कुछ काम करता है कि आप के लिए यह चाहते है

>>> from twisted.python.reflect import namedAny 
>>> namedAny("operator.eq") 
<built-in function eq> 
>>> namedAny("pysqlite2.dbapi2.connect") 
<built-in function connect> 
>>> namedAny("os") 
<module 'os' from '/usr/lib/python2.5/os.pyc'> 
+0

कि बहुत उपयोगी है की किसी भी सामग्री का उपयोग कर सकते है, लेकिन मैं वास्तव में के लिए किसी अन्य की जरूरत नहीं है मेरे कार्यक्रम में मुड़ गया। हालांकि, संस्थापक (!) के रूप में, आप शायद मुझसे अधिक संभावनाओं के बारे में अधिक जानकार हैं (कभी इसका इस्तेमाल नहीं किया)। – dwestbrook

32

अजगर 2.7 importlib है, बिंदीदार रास्तों की उम्मीद

import importlib 
foo = importlib.import_module('a.dotted.path') 
instance = foo.SomeClass() 
+2

एक पायथन 2.6 पैकेज भी है जो इस कार्यक्षमता का समर्थन करता है। https://pypi.python.org/pypi/importlib/ – melinath

1

के रूप में अजगर 2.6 के लिए हल है, मैं इस टुकड़ा लिखा है:

def import_and_get_mod(str, parent_mod=None): 
    """Attempts to import the supplied string as a module. 
    Returns the module that was imported.""" 
    mods = str.split('.') 
    child_mod_str = '.'.join(mods[1:]) 
    if parent_mod is None: 
     if len(mods) > 1: 
      #First time this function is called; import the module 
      #__import__() will only return the top level module 
      return import_and_get_mod(child_mod_str, __import__(str)) 
     else: 
      return __import__(str) 
    else: 
     mod = getattr(parent_mod, mods[0]) 
     if len(mods) > 1: 
      #We're not yet at the intended module; drill down 
      return import_and_get_mod(child_mod_str, mod) 
     else: 
      return mod 
16

दस्तावेज़ीकरण में समझाया गया एक आसान समाधान है:

यदि आप बस नाम से एक मॉड्यूल (संभावित रूप से एक पैकेज के भीतर) आयात करना चाहते हैं, तो आप __import __() को कॉल कर सकते हैं और फिर इसे sys में देख सकते हैं।मॉड्यूल:

>>> import sys 
>>> name = 'foo.bar.baz' 
>>> __import__(name) 
<module 'foo' from ...> 
>>> baz = sys.modules[name] 
>>> baz 
<module 'foo.bar.baz' from ...> 
0

तरह से मैंने किया था

foo = __import__('foo', globals(), locals(), ["bar"], -1) 
foobar = eval("foo.bar") 

तो मैं द्वारा

foobar.functionName() 
+1

क्यों न केवल उस बिंदु पर 'foo.bar'? –

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