python पायथन में गतिशील मॉड्यूल आयात




python-import (8)

मैं एक पायथन एप्लिकेशन लिख रहा हूं जो एक तर्क के रूप में एक आदेश के रूप में लेता है, उदाहरण के लिए:

$ python myapp.py command1

मैं चाहता हूं कि एप्लिकेशन एक्स्टेंसिबल हो, यानी, नए मॉड्यूल को जोड़ने में सक्षम होने के लिए जो मुख्य अनुप्रयोग स्रोत को बदलने के बिना नए आदेशों को लागू करता है। पेड़ कुछ ऐसा दिखता है:

myapp/
    __init__.py
    commands/
        __init__.py
        command1.py
        command2.py
    foo.py
    bar.py

तो मैं चाहता हूं कि एप्लिकेशन रनटाइम पर उपलब्ध कमांड मॉड्यूल ढूंढें और उपयुक्त एक निष्पादित करें।

वर्तमान में यह कुछ इस प्रकार लागू किया गया है:

command = sys.argv[1]
try:
    command_module = __import__("myapp.commands.%s" % command, fromlist=["myapp.commands"])
except ImportError:
    # Display error message

command_module.run()

यह ठीक काम करता है, मैं बस सोच रहा हूं कि क्या हम इस कोड के साथ क्या कर रहे हैं, इसे पूरा करने के लिए संभवतः एक और बेवकूफ तरीका है।

ध्यान दें कि मैं विशेष रूप से अंडे या विस्तार बिंदुओं का उपयोग नहीं करना चाहता हूं। यह एक ओपन-सोर्स प्रोजेक्ट नहीं है और मुझे उम्मीद है कि वहां "प्लगइन्स" न हों। बिंदु मुख्य अनुप्रयोग कोड को सरल बनाना है और प्रत्येक बार एक नया कमांड मॉड्यूल जोड़ा जाने पर इसे संशोधित करने की आवश्यकता को हटा देना है।


2.7 / 3.1 से पुराने पायथन के साथ, यह बहुत कुछ है कि आप इसे कैसे करते हैं। नए संस्करणों के लिए, importlib.import_module और 3.1+ के लिए importlib.import_module देखें।

यदि आप भी चाहते हैं तो आप exec उपयोग कर सकते हैं।

ध्यान दें कि आप ऐसा करके मॉड्यूल की एक सूची आयात कर सकते हैं:

>>> moduleNames = ['sys', 'os', 're', 'unittest'] 
>>> moduleNames
['sys', 'os', 're', 'unittest']
>>> modules = map(__import__, moduleNames)

पाइथन में सीधे डाइव से फिसल गया



नीचे दिया गया टुकड़ा मेरे लिए काम किया:

>>>import imp; 
>>>fp, pathname, description = imp.find_module("/home/test_module"); 
>>>test_module = imp.load_module("test_module", fp, pathname, description);
>>>print test_module.print_hello();

अगर आप शेल-स्क्रिप्ट में आयात करना चाहते हैं:

python -c '<above entire code in one line>'

जैसा कि बताया गया है कि imp मॉड्यूल आपको कार्य लोड कर रहा है:

imp.load_source(name, path)
imp.load_compiled(name, path)

मैंने कुछ ऐसा करने के लिए पहले इनका उपयोग किया है।

मेरे मामले में मैंने परिभाषित विधियों के साथ एक विशिष्ट वर्ग को परिभाषित किया था। एक बार जब मैं मॉड्यूल लोड करता हूं तो मैं जांचता हूं कि कक्षा मॉड्यूल में थी या नहीं, और उसके बाद उस वर्ग का एक उदाहरण बनाएं, ऐसा कुछ:

import imp
import os

def load_from_file(filepath):
    class_inst = None
    expected_class = 'MyClass'

    mod_name,file_ext = os.path.splitext(os.path.split(filepath)[-1])

    if file_ext.lower() == '.py':
        py_mod = imp.load_source(mod_name, filepath)

    elif file_ext.lower() == '.pyc':
        py_mod = imp.load_compiled(mod_name, filepath)

    if hasattr(py_mod, expected_class):
        class_inst = getattr(py_mod, expected_class)()

    return class_inst

@monkut के समाधान के समान ही, लेकिन यहां वर्णित पुन: प्रयोज्य और त्रुटि सहनशीलता stamat.wordpress.com/dynamic-module-import-in-python :

import os
import imp

def importFromURI(uri, absl):
    mod = None
    if not absl:
        uri = os.path.normpath(os.path.join(os.path.dirname(__file__), uri))
    path, fname = os.path.split(uri)
    mname, ext = os.path.splitext(fname)

    if os.path.exists(os.path.join(path,mname)+'.pyc'):
        try:
            return imp.load_compiled(mname, uri)
        except:
            pass
    if os.path.exists(os.path.join(path,mname)+'.py'):
        try:
            return imp.load_source(mname, uri)
        except:
            pass

    return mod

पायथन 2.7 के लिए अनुशंसित तरीका और बाद में importlib मॉड्यूल का उपयोग importlib है:

my_module = importlib.import_module('os.path')

यदि आप इसे अपने स्थानीय लोगों में चाहते हैं:

>>> mod = 'sys'
>>> locals()['my_module'] = __import__(mod)
>>> my_module.version
'2.6.6 (r266:84297, Aug 24 2010, 18:46:32) [MSC v.1500 32 bit (Intel)]'

globals() साथ काम करेगा globals()


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

import sys, glob
sys.path.append('/home/marc/python/importtest/modus')
fl = glob.glob('modus/*.py')
modulist = []
adapters=[]
for i in range(len(fl)):
    fl[i] = fl[i].split('/')[1]
    fl[i] = fl[i][0:(len(fl[i])-3)]
    modulist.append(getattr(__import__(fl[i]),fl[i]))
    adapters.append(modulist[i]())

यह फ़ोल्डर 'मॉडस' से मॉड्यूल लोड करता है। मॉड्यूल में एक ही वर्ग होता है जिसमें मॉड्यूल नाम के समान नाम होता है। जैसे फ़ाइल मोडस / modu1.py में शामिल हैं:

class modu1():
    def __init__(self):
        self.x=1
        print self.x

नतीजा गतिशील रूप से लोड वर्गों "एडेप्टर" की एक सूची है।





python-import