स्ट्रिंग से, फ़ाइल में डायनामिक तरीके से आयात करें


84

मेरे पास एक तार है, कहते हैं abc.def.ghi.jkl.myfile.mymethod:। मैं गतिशील रूप से कैसे आयात mymethodकरूं?

यहाँ है कि मैं इसके बारे में कैसे गया:

def get_method_from_file(full_path):
    if len(full_path) == 1:
        return map(__import__,[full_path[0]])[0]
    return getattr(get_method_from_file(full_path[:-1]),full_path[-1])


if __name__=='__main__':
    print get_method_from_file('abc.def.ghi.jkl.myfile.mymethod'.split('.'))

मुझे आश्चर्य है कि अगर आयात करने वाले अलग-अलग मॉड्यूल की आवश्यकता है।

संपादित करें: मैं पाइथन संस्करण 2.6.5 का उपयोग कर रहा हूं।

जवाबों:


111

पायथन 2.7 से आप importlib.import_module () फ़ंक्शन का उपयोग कर सकते हैं । आप एक मॉड्यूल आयात कर सकते हैं और उसके भीतर परिभाषित एक वस्तु का उपयोग निम्नलिखित कोड के साथ कर सकते हैं:

from importlib import import_module

p, m = name.rsplit('.', 1)

mod = import_module(p)
met = getattr(mod, m)

met()

2
पायथन डॉक्स को ध्यान में रखते हुए वर्थ का उपयोग importlib.import_module()करने की सलाह देते हैं __import__(): docs.python.org/2/library/functions.html#__import__ - 2.7+ के लिए।
BoltzmannBrain

4
import_module + rsplit = एक सच्चा तरीका।
सेसिल करी

32

आपको अलग-अलग मॉड्यूल आयात करने की आवश्यकता नहीं है। यह उस मॉड्यूल को आयात करने के लिए पर्याप्त है जिसे आप किसी नाम से आयात करना चाहते हैं और fromlistतर्क प्रदान करना चाहते हैं :

def import_from(module, name):
    module = __import__(module, fromlist=[name])
    return getattr(module, name)

अपने उदाहरण के लिए abc.def.ghi.jkl.myfile.mymethod, इस फ़ंक्शन को कॉल करें

import_from("abc.def.ghi.jkl.myfile", "mymethod")

(ध्यान दें कि मॉड्यूल-स्तर के कार्यों को पायथन में फ़ंक्शन कहा जाता है, न कि तरीके।)

ऐसे सरल कार्य के लिए, importlibमॉड्यूल का उपयोग करने में कोई फायदा नहीं है ।


import_from () ने मुझे सही दिशा में इशारा किया। myClass = getattr(__import__("module.to.import", fromlist=["myClassName"]), "myClassName")। सहायता के लिए धन्यवाद!
फिदो

1
__import__दृष्टिकोण काम करता है। लेकिन दौड़ने की कोशिश करो help(__import__)। यह कहता है "क्योंकि यह फ़ंक्शन पाइथन इंटरप्रेटर द्वारा उपयोग के लिए है न कि सामान्य उपयोग के लिए यह importlib.import_module()प्रोग्रामेटिक रूप से मॉड्यूल आयात करने के लिए उपयोग करने के लिए बेहतर है ।"
ट्वासब्रिलिग

5
@ वॉटसब्रिलिग: जब मैंने इस प्रश्न का उत्तर दिया, तो पायथन 2.5 और 2.6 अभी भी व्यापक उपयोग में थे। आज, इसके importlibबजाय इसका उपयोग करना निश्चित रूप से सबसे अच्छा है ।
स्वेन मार्नाच

1
अच्छा है धन्यवाद। इसे प्रतिबिंबित करने के लिए उत्तर को अपडेट करने के लिए एक अच्छा विचार हो सकता है।
ट्वासब्रिलिग

26

पायथन <2.7 के लिए बिल्टिन विधि __ import__ का उपयोग किया जा सकता है:

__import__('abc.def.ghi.jkl.myfile.mymethod', fromlist=[''])

पायथन के लिए> = 2.7 या 3.1 सुविधाजनक विधि importlib.import_module जोड़ा गया है। बस अपने मॉड्यूल को इस तरह आयात करें:

importlib.import_module('abc.def.ghi.jkl.myfile.mymethod')

अपडेट : अद्यतन संस्करण टिप्पणियों के अनुसार ( मुझे लगता है मैं मानता चाहिए स्ट्रिंग पढ़ने नहीं था अंत तक आयात करने के लिए और मैं तथ्य यह है कि एक मॉड्यूल की एक विधि आयातित किया जाना चाहिए और नहीं एक मॉड्यूल में ही याद किया) :

अजगर <2.7:

mymethod = getattr(__import__("abc.def.ghi.jkl.myfile", fromlist=["mymethod"]))

पायथन> = 2.7:

mymethod = getattr(importlib.import_module("abc.def.ghi.jkl.myfile"), "mymethod")

6
इनमें से कोई भी समाधान काम नहीं करेगा क्योंकि पहले पैरामीटर में और दोनों में एक मॉड्यूल नाम होना चाहिए । __import__()importlib.import_module()
क्रि हार्डी

1
importlib.import_module ('abc.def.ghi.jkl.myfile.mymethod') काम नहीं करेगा क्योंकि आपको "पूर्ण या सापेक्ष शब्दों में आयात करने के लिए कौन सा मॉड्यूल" निर्दिष्ट करना है और विधि का "योग्य" नाम नहीं।
frm

यह काम नहीं करता है, जाहिर है, आयात करने के लिए पहला पैरामीटर एक मॉड्यूल होना चाहिए, न कि एक स्ट्रिंग।
लक्ष्मण प्रसाद

11

यह स्पष्ट नहीं है कि आप अपने स्थानीय नामस्थान पर क्या करने की कोशिश कर रहे हैं। मुझे लगता है कि आप my_methodएक स्थानीय, टाइपिंग के रूप में चाहते हैं output = my_method()?

# This is equivalent to "from a.b.myfile import my_method"
the_module = importlib.import_module("a.b.myfile")
same_module = __import__("a.b.myfile")
# import_module() and __input__() only return modules
my_method = getattr(the_module, "my_method")

# or, more concisely,
my_method = getattr(__import__("a.b.myfile"), "my_method")
output = my_method()

जब आप केवल my_methodस्थानीय नामस्थान में जोड़ते हैं , तो आप मॉड्यूल की श्रृंखला को लोड करते हैं। आप sys.modulesआयात से पहले और बाद की चाबियों को देखकर बदलाव देख सकते हैं । मुझे उम्मीद है कि यह स्पष्ट है और आपके अन्य उत्तरों की तुलना में अधिक सटीक है।

पूर्णता के लिए, यह है कि आप पूरी श्रृंखला को कैसे जोड़ते हैं।

# This is equivalent to "import a.b.myfile"
a = __import__("a.b.myfile")
also_a = importlib.import_module("a.b.myfile")
output = a.b.myfile.my_method()

# This is equivalent to "from a.b import myfile"
myfile = __import__("a.b.myfile", fromlist="a.b")
also_myfile = importlib.import_module("a.b.myfile", "a.b")
output = myfile.my_method()

और, अंत में, यदि आप उपयोग कर रहे हैं __import__()और कार्यक्रम शुरू होने के बाद आपने खोज पथ को संशोधित किया है , तो आपको उपयोग करने की आवश्यकता हो सकती है __import__(normal args, globals=globals(), locals=locals())। क्यों एक जटिल चर्चा है।


का पहला उदाहरण the_moduleऔर same_moduleक्या गलत है और विभिन्न परिणाम। नीचा दिखानेवाला।
स्लीपाइकल जूल 22'14

7
from importlib import import_module

name = "file.py".strip('.py')
# if Path like : "path/python/file.py" 
# use name.replaces("/",".")

imp = import_module(name)

# get Class From File.py
model = getattr(imp, "classNameImportFromFile")

NClass = model() # Class From file 

2
उत्तर के लिए धन्यवाद, बस एक छोटी सी समस्या: मुझे नहीं लगता कि .strip()आपके द्वारा बताए गए मामले में सही ढंग से व्यवहार नहीं किया गया है। विशेष रूप से, यदि फ़ाइल "py" से शुरू होती है, तो उन पात्रों को भी हटा दिया जाएगा। उदाहरण के लिए, "pyfile.py".strip(".py")उत्पादन "file", जहां यह पसंद किया जाएगा कि यह "pyfile"इस मामले में उत्पादन करता है। name.replace(".py","")हालांकि ठीक काम करता है।
jxmorris12

1

इस वेबसाइट का एक अच्छा समाधान है: load_class । मैं इसे इस तरह से उपयोग करता हूं:

foo = load_class(package.subpackage.FooClass)()
type(foo) # returns FooClass

अनुरोध के अनुसार, यहाँ वेब लिंक से कोड है:

import importlib

def load_class(full_class_string):
    """
    dynamically load a class from a string
    """

    class_data = full_class_string.split(".")
    module_path = ".".join(class_data[:-1])
    class_str = class_data[-1]

    module = importlib.import_module(module_path)
    # Finally, we retrieve the Class
    return getattr(module, class_str)

कृपया दिए गए लिंक से सारांश / कोड शामिल करें। लिंक-ओनली उत्तर महान नहीं हैं क्योंकि वे लिंक रोट के लिए प्रवण हैं।
फिर भी एक और उपयोगकर्ता

0

उपयोग करें importlib(केवल 2.7+)।


1
मैं 2.6.5 का उपयोग करता हूं। क्या मैं एक from __future__काम कर सकता हूँ ?
लक्ष्मण प्रसाद

5
नहीं, __future__भाषा सुविधाओं के लिए है, नए stdlib मॉड्यूल नहीं।
ThiefMaster

1
__import__उपरोक्त उदाहरणों में buit-in का उपयोग करें । यह 2.5 और फिर, कीवर्ड्स के बिना, इससे पहले काम करता है।
चार्ल्स मेरियम

0

जिस तरह से मैं इस पर जाता हूं (साथ ही कई अन्य पुस्तकालय, जैसे कि तोरण और पेस्ट, यदि मेरी स्मृति मुझे सही ढंग से कार्य करती है) मॉड्यूल मोड को उनके बीच ':' का उपयोग करके फ़ंक्शन / विशेषता नाम से अलग करना है। । निम्नलिखित उदाहरण देखें:

'abc.def.ghi.jkl.myfile:mymethod'

यह import_from(path)नीचे दिए गए फ़ंक्शन को उपयोग करने के लिए थोड़ा आसान बनाता है।

def import_from(path):
    """
    Import an attribute, function or class from a module.
    :attr path: A path descriptor in the form of 'pkg.module.submodule:attribute'
    :type path: str
    """
    path_parts = path.split(':')
    if len(path_parts) < 2:
        raise ImportError("path must be in the form of pkg.module.submodule:attribute")
    module = __import__(path_parts[0], fromlist=path_parts[1])
    return getattr(module, path_parts[1])


if __name__=='__main__':
    func = import_from('a.b.c.d.myfile:mymethod')
    func()

1
किसी भी व्यक्ति को ऐसा क्यों करना चाहिए? इससे कॉल करने वाले को एक कोलोन के साथ मॉड्यूल नाम और विशेषता नाम में शामिल होने की आवश्यकता होती है, और फ़ंक्शन को फिर से कोलन में विभाजित करने की आवश्यकता होती है। केवल पहली जगह में दो मापदंडों का उपयोग क्यों नहीं किया जाता है?
स्वेन मार्नाच

1
अक्सर, ऐसी स्थिति जहां यह सामने आएगा अगर आप कॉन्फ़िगरेशन फ़ाइलों (.yaml, .ini, आदि) का उपयोग करके एक फ्रेमवर्क से अपने आवेदन में कॉलबैक करते हैं। फिर, आप यह निर्दिष्ट कर सकते हैं कि आपकी कॉन्फ़िगरेशन फ़ाइल में एक स्ट्रिंग के साथ किस फ़ंक्शन को कॉल करना चाहिए, आदि।
क्रिस हार्डी

ठीक है, हाँ, आप इसे कॉन्फ़िगरेशन फ़ाइल सिंटैक्स के रूप में चुनना चाह सकते हैं। लेकिन यह ओपी के सवाल से कैसे संबंधित है? (और यहां तक ​​कि अगर मैंने इसे अपनी कॉन्फिग फाइल सिंटैक्स के रूप में चुना था, तो मैं इसे अपनी कॉन्फिग फाइल पार्सर द्वारा पार्स करना पसंद करूंगा, रैंडम एपीआई फंक्शंस द्वारा नहीं।)
स्वेन मार्नाच

-1

इस बारे में कैसा है :

def import_module(name):

    mod = __import__(name)
    for s in name.split('.')[1:]:
        mod = getattr(mod, s)
    return mod

जादू की विधि का उपयोग हतोत्साहित किया जाता है। इसके बजाय आयात का उपयोग करें।
डेफिनेरा

क्या आप इस बारे में विस्तार से बता सकते हैं कि यह हतोत्साहित करने वाला क्यों है? @ दीपिनहेरा
अयमान अलसाड़ी

अच्छी तरह से क्योंकि जादू विधियों को दुभाषिया द्वारा बुलाया जाना है, हमारे कोड द्वारा स्पष्ट रूप से नहीं। उन्हें स्पष्ट रूप से कॉल करके, हम भरोसा करते हैं कि उनके हस्ताक्षर कभी नहीं बदलेंगे, हालांकि यह भविष्य के भाषा संस्करणों में बदल सकता है।
डेफिनेरा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.