पूर्ण पथ को देखते हुए मॉड्यूल को कैसे आयात किया जाए?


1138

मैं अपने पूर्ण पथ को देखते हुए पायथन मॉड्यूल को कैसे लोड कर सकता हूं? ध्यान दें कि फ़ाइल फ़ाइल सिस्टम में कहीं भी हो सकती है, क्योंकि यह एक कॉन्फ़िगरेशन विकल्प है।


21
अच्छा और सरल प्रश्न - और उपयोगी उत्तर लेकिन वे मुझे आश्चर्यचकित करते हैं कि अजगर मंत्र के साथ क्या हुआ था "ऐसा करने के लिए एक स्पष्ट तरीका है" .. यह एक एकल या सरल और स्पष्ट उत्तर की तरह कुछ भी नहीं लगता है। इस तरह के एक मौलिक ऑपरेशन के लिए हास्यास्पद रूप से हैक और संस्करण-निर्भर लगता है (और यह नए संस्करणों में और अधिक फूला हुआ दिखता है ..)।
12

जवाबों:


1279

पायथन 3.5+ उपयोग के लिए:

import importlib.util
spec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py")
foo = importlib.util.module_from_spec(spec)
spec.loader.exec_module(foo)
foo.MyClass()

पायथन 3.3 और 3.4 उपयोग के लिए:

from importlib.machinery import SourceFileLoader

foo = SourceFileLoader("module.name", "/path/to/file.py").load_module()
foo.MyClass()

(हालांकि यह अजगर 3.4 में चित्रित किया गया है।)

पायथन 2 उपयोग के लिए:

import imp

foo = imp.load_source('module.name', '/path/to/file.py')
foo.MyClass()

संकलित पायथन फ़ाइलों और डीएलएल के लिए समान सुविधा कार्य हैं।

Http://bugs.python.org/issue21436 पर भी देखें ।


53
अगर मुझे नामस्थान पता था - 'मॉड्यूल.नाम' - मैं पहले से ही उपयोग करूंगा __import__
श्रीधर रत्नाकुमार

62
@SridharRatnakumar imp.load_sourceकेवल .__name__दिए गए मॉड्यूल के पहले तर्क का मान सेट करता है। यह लोडिंग को प्रभावित नहीं करता है।
दान डी।

17
@DanD। - शब्दकोश imp.load_source()में बनाई गई नई प्रविष्टि की कुंजी का पहला तर्क निर्धारित करता है sys.modules, इसलिए पहला तर्क वास्तव में लोडिंग को प्रभावित करता है।
ब्रैंडन रोड्स

9
impमॉड्यूल संस्करण 3.4 के बाद से हटा दिया गया है: impपैकेज के पक्ष में निंदा लंबित है importlib
चायल दस ब्रिंक

9
@AXO और अधिक एक बिंदु के लिए आश्चर्य की बात है कि क्यों कुछ सरल और बुनियादी के रूप में इस के लिए इतना जटिल होना चाहिए। यह कई अन्य भाषाओं में नहीं है।
चट्टानी

422

Sys.path (imp का उपयोग करने से अधिक) के लिए एक पथ जोड़ने का लाभ यह है कि यह एकल पैकेज से एक से अधिक मॉड्यूल आयात करते समय चीजों को सरल करता है। उदाहरण के लिए:

import sys
# the mock-0.3.1 dir contains testcase.py, testutils.py & mock.py
sys.path.append('/foo/bar/mock-0.3.1')

from testcase import TestCase
from testutils import RunTests
from mock import Mock, sentinel, patch

13
हम sys.path.appendएक निर्देशिका के बजाय एक अजगर फ़ाइल को इंगित करने के लिए कैसे उपयोग करते हैं ?
फणी

28
:-) शायद आपका प्रश्न एक StackOverflow प्रश्न के रूप में बेहतर होगा, उत्तर पर टिप्पणी नहीं।
डेरिल स्पिट्जर

3
अजगर पथ में ज़िप अभिलेखागार, "अंडे" (एक जटिल प्रकार का ज़िप अभिलेखागार) हो सकते हैं, आदि मॉड्यूल उनमें से आयात किए जा सकते हैं। इसलिए पथ तत्व वास्तव में फाइलों के कंटेनर हैं, लेकिन वे जरूरी निर्देशिका नहीं हैं।
एलेक्सिस

12
इस तथ्य से सावधान रहें कि पायथन कैश स्टेटमेंट आयात करता है। दुर्लभ मामले में कि आपके पास एक एकल वर्ग नाम (classX) साझा करने वाले दो अलग-अलग फ़ोल्डर हैं, sys.path के लिए एक पथ जोड़ने का दृष्टिकोण, classX आयात करना, पथ को निकालना और रीमिंग पथ के लिए पुनरावृत्ति करने से काम नहीं चलेगा। पायथन हमेशा अपने कैश से प्रथम पथ से कक्षा को लोड करेगा। मेरे मामले में मैंने एक प्लगइन सिस्टम बनाने का लक्ष्य रखा था जहाँ सभी प्लगइन्स एक विशिष्ट क्लासएक्स लागू करते हैं। मैंने SourceFileLoader का उपयोग करते हुए समाप्त किया , ध्यान दें कि इसका पदावनति विवादास्पद है
ComFreek

3
इस दृष्टिकोण पर ध्यान दें आयातित मॉड्यूल को उसी dir से अन्य मॉड्यूल आयात करने की अनुमति देता है, जो मॉड्यूल अक्सर करते हैं, जबकि स्वीकृत उत्तर का दृष्टिकोण (कम से कम 3.7 पर) नहीं है। importlib.import_module(mod_name)यहां स्पष्ट आयात के बजाय इसका उपयोग किया जा सकता है यदि मॉड्यूल नाम रनटाइम पर ज्ञात नहीं है, तो मैं sys.path.pop()अंत में एक जोड़ दूंगा , हालांकि, यह मानकर कि आयातित कोड अधिक मॉड्यूल आयात करने की कोशिश नहीं करता है क्योंकि इसका उपयोग किया जाता है।
एली_बाय

43

यदि आपका शीर्ष-स्तरीय मॉड्यूल फ़ाइल नहीं है, लेकिन __init__.py के साथ निर्देशिका के रूप में पैक किया गया है, तो स्वीकृत समाधान लगभग काम करता है, लेकिन काफी नहीं। पायथन 3.5+ में निम्न कोड की आवश्यकता होती है (जोड़ा गया पंक्ति जो 'sys.modules' से शुरू होता है) पर ध्यान दें:

MODULE_PATH = "/path/to/your/module/__init__.py"
MODULE_NAME = "mymodule"
import importlib
import sys
spec = importlib.util.spec_from_file_location(MODULE_NAME, MODULE_PATH)
module = importlib.util.module_from_spec(spec)
sys.modules[spec.name] = module 
spec.loader.exec_module(module)

इस पंक्ति के बिना, जब exec_module निष्पादित किया जाता है, तो यह आपके शीर्ष स्तर __init__.py में शीर्ष स्तर मॉड्यूल नाम के सापेक्ष आयात को बांधने की कोशिश करता है - इस मामले में "mymodule"। लेकिन "mymodule" को अभी तक लोड नहीं किया गया है, इसलिए आपको त्रुटि मिलेगी "SystemError: पैरेंट मॉड्यूल 'mymodule' लोड नहीं किया गया है, सापेक्ष आयात नहीं कर सकता है"। इसलिए आपको लोड करने से पहले नाम को बांधने की आवश्यकता है। इसका कारण सापेक्ष आयात प्रणाली का मूलभूत रूपांतर है: "अपरिवर्तनीय धारण यह है कि यदि आपके पास sys.modules ['स्पैम'] और sys.modules ['spam.foo'] (जैसा कि आप उपरोक्त आयात के बाद करेंगे) ), बाद वाले को पूर्व की foo विशेषता के रूप में प्रकट होना चाहिए " जैसा कि यहां चर्चा की गई है


आपका बहुत बहुत धन्यवाद! यह विधि सबमॉड्यूल के बीच सापेक्ष आयात को सक्षम बनाता है। महान!
तेनायप

यह उत्तर यहां के दस्तावेज़ से मेल खाता है: docs.python.org/3/library/…
टिम लुड्विंस्की 16

1
लेकिन क्या है mymodule?
गुलज़ार

@ गुलज़ार, यह वह नाम है जो आप अपने मॉड्यूल को देना चाहते हैं, जैसे कि आप बाद में कर सकते हैं: "मैमोडुले इंपोर्ट मायक्लास से"
इडोडो

तो ... /path/to/your/module/वास्तव में है /path/to/your/PACKAGE/? और mymoduleतुम्हारा मतलब है myfile.py?
गुलजार

37

अपने मॉड्यूल को आयात करने के लिए, आपको इसकी निर्देशिका को पर्यावरण चर में अस्थायी या स्थायी रूप से जोड़ना होगा।

अस्थायी रूप से

import sys
sys.path.append("/path/to/my/modules/")
import my_module

स्थायी रूप से

अपनी .bashrcफ़ाइल में (लाइनक्स में) निम्न लाइन जोड़कर source ~/.bashrcटर्मिनल में प्रवेश करें:

export PYTHONPATH="${PYTHONPATH}:/path/to/my/modules/"

क्रेडिट / स्रोत: saarrrr , एक और स्टैकएक्सचेंज प्रश्न


3
यह "अस्थायी" समाधान एक महान उत्तर है यदि आप एक परियोजना को चारों ओर एक बृहस्पति नोटबुक में ठेस करना चाहते हैं।
fordy

लेकिन ... यह मार्ग के साथ खतरनाक छेड़छाड़ है
Shai Alon

@ शायलन आप रास्ते जोड़ रहे हैं, इसलिए जब आप एक कंप्यूटर से दूसरे कंप्यूटर में कोड ट्रांसफर करते हैं, तो इसके अलावा कोई खतरा नहीं है, रास्ते गड़बड़ हो सकते हैं। इसलिए, पैकेज के विकास के लिए, मैं केवल स्थानीय पैकेजों का आयात करता हूं। इसके अलावा, पैकेज के नाम अद्वितीय होने चाहिए। यदि आप चिंतित हैं, तो अस्थायी समाधान का उपयोग करें।
मिलादियस

28

ऐसा लगता है कि आप विशेष रूप से कॉन्फ़िगरेशन फ़ाइल को आयात नहीं करना चाहते हैं (जिसमें कई साइड इफेक्ट्स और अतिरिक्त जटिलताएं शामिल हैं), आप बस इसे चलाना चाहते हैं, और परिणामी नामस्थान तक पहुंचने में सक्षम हो सकते हैं। मानक पुस्तकालय विशेष रूप से runpy.run_path के रूप में इसके लिए एक एपीआई प्रदान करता है :

from runpy import run_path
settings = run_path("/path/to/file.py")

वह इंटरफ़ेस Python 2.7 और Python 3.2+ में उपलब्ध है


मुझे यह तरीका पसंद है लेकिन जब मुझे run_path का ऐसा डिक्शनरी मिलता है, जिसे मैं एक्सेस नहीं कर सकता?
स्टीफन एलवुड

"आप एक्सेस नहीं कर सकते" से क्या मतलब है? आप इसे से आयात नहीं कर सकते (यही कारण है कि यह केवल एक अच्छा विकल्प है जब आयात शैली का उपयोग वास्तव में आवश्यक नहीं है है है), लेकिन सामग्री नियमित रूप से dict एपीआई (के माध्यम से उपलब्ध होना चाहिए result[name], result.get('name', default_value), आदि)
ncoghlan

इस जवाब को कम करके आंका गया है। यह बहुत छोटा और सरल है! इससे भी बेहतर, अगर आपको एक उचित मॉड्यूल नामस्थान की आवश्यकता है, तो आप कुछ ऐसा कर सकते हैं from runpy import run_path; from argparse import Namespace; mod = Namespace(**run_path('path/to/file.py'))
RuRo

20

आप ऐसा कुछ भी कर सकते हैं और निर्देशिका को जोड़ सकते हैं कि कॉन्फ़िगरेशन फ़ाइल पायथन लोड पथ में बैठा है, और फिर बस एक सामान्य आयात करें, यह मानते हुए कि आप इस मामले में फ़ाइल का नाम पहले से जानते हैं, इस मामले में "कॉन्फ़िगरेशन"।

गन्दा, लेकिन यह काम करता है।

configfile = '~/config.py'

import os
import sys

sys.path.append(os.path.dirname(os.path.expanduser(configfile)))

import config

जो कि गतिशील नहीं है।
Shai Alon

मैंने कोशिश की: config_file = 'setup-for-chats', setup_file = get_setup_file (config_file + ".py"), sys.path.append (os.path.dirname (os.path.expanduser (setup_file))), आयात config_file। >> "ImportError: config_file नाम का कोई मॉड्यूल नहीं"
Shai Alon


13
def import_file(full_path_to_module):
    try:
        import os
        module_dir, module_file = os.path.split(full_path_to_module)
        module_name, module_ext = os.path.splitext(module_file)
        save_cwd = os.getcwd()
        os.chdir(module_dir)
        module_obj = __import__(module_name)
        module_obj.__file__ = full_path_to_module
        globals()[module_name] = module_obj
        os.chdir(save_cwd)
    except:
        raise ImportError

import_file('/home/somebody/somemodule.py')

37
जब यह पहले से ही मानक पुस्तकालय द्वारा संबोधित किया जाता है, तो छोटी गाड़ी कोड की 14 लाइनें क्यों लिखें? आपने फॉर्मेट या फुल_पैथ_टो_मॉडल या ऑस.व्हाटएवर ऑपरेशंस की सामग्री पर जाँच करने में त्रुटि नहीं की है; और कैच-ऑल except:क्लॉज का उपयोग करना शायद ही कभी एक अच्छा विचार है।
क्रिस जॉनसन

आपको अधिक "कोशिश-अंत" का उपयोग यहां करना चाहिए। जैसेsave_cwd = os.getcwd() try: … finally: os.chdir(save_cwd)
- एसई बुराई है

11
@ क्रिस जॉनसन this is already addressed by the standard libraryहाँ, लेकिन अजगर को पिछड़े-संगत नहीं होने की आदत है ... जैसा कि उत्तर में कहा गया है कि 3.3 से पहले और बाद में 2 अलग-अलग तरीके हैं। उस मामले में, मैं नहीं बल्कि मक्खी पर चेक संस्करण की तुलना में अपने स्वयं के सार्वभौमिक कार्य लिखना चाहते हैं। और हाँ, शायद यह कोड बहुत अच्छी तरह से त्रुटि-सुरक्षित नहीं है, लेकिन यह एक विचार दिखाता है (जो कि os.chdir (), मैं हालांकि इसके बारे में नहीं है), जिसके आधार पर मैं एक बेहतर कोड लिख सकता हूं। इसलिए +1।
सुशी271

13

यहाँ कुछ कोड है जो 2.7-3.5 से और शायद अन्य लोगों से भी सभी पायथन संस्करणों में काम करता है।

config_file = "/tmp/config.py"
with open(config_file) as f:
    code = compile(f.read(), config_file, 'exec')
    exec(code, globals(), locals())

मैंने इसका परीक्षण किया। यह बदसूरत हो सकता है लेकिन अभी तक केवल एक ही है जो सभी संस्करणों में काम करता है।


1
इस जवाब ने मेरे लिए काम किया, जहां load_sourceऐसा नहीं हुआ क्योंकि यह स्क्रिप्ट आयात करता है और आयात के समय मॉड्यूल और ग्लोबल्स को स्क्रिप्ट एक्सेस प्रदान करता है।
क्लीव

13

मैं @ सेबस्टियनरिटौ के अद्भुत उत्तर (पायथन> ३.४ के अनुसार) के थोड़े संशोधित संस्करण के साथ आया हूं, जो आपको spec_from_loaderइसके बजाय किसी मॉड्यूल के रूप में किसी भी एक्सटेंशन के साथ फाइल लोड करने की अनुमति देगा spec_from_file_location:

from importlib.util import spec_from_loader, module_from_spec
from importlib.machinery import SourceFileLoader 

spec = spec_from_loader("module.name", SourceFileLoader("module.name", "/path/to/file.py"))
mod = module_from_spec(spec)
spec.loader.exec_module(mod)

स्पष्ट रूप SourceFileLoaderसे पथ को एन्कोडिंग करने का लाभ यह है कि मशीनरी एक्सटेंशन से फ़ाइल के प्रकार का पता लगाने की कोशिश नहीं करेगी। इसका मतलब है कि आप .txtइस पद्धति का उपयोग करके किसी फ़ाइल की तरह कुछ लोड कर सकते हैं , लेकिन आप spec_from_file_locationलोडर को निर्दिष्ट किए बिना ऐसा नहीं कर सकते क्योंकि इसमें .txtनहीं है importlib.machinery.SOURCE_SUFFIXES


13

क्या आपका मतलब लोड या इंपोर्ट है?

आप sys.pathसूची में हेरफेर कर सकते हैं अपने मॉड्यूल के लिए पथ निर्दिष्ट करें, फिर अपने मॉड्यूल को आयात करें। उदाहरण के लिए, यहां एक मॉड्यूल दिया गया है:

/foo/bar.py

तुम यह कर सकते थे:

import sys
sys.path[0:0] = ['/foo'] # puts the /foo directory at the start of your path
import bar

1
@Wheat क्यों sys.path [0: 0] के बजाय sys.path [0]?
user618677

5
B / c sys.path [0] = xy पथ के दौरान पहली पथ आइटम को ओवरराइट करता है [0: 0] = xy path.insert (0, xy) के बराबर है
dom0

2
hm path.insert ने मेरे लिए काम किया लेकिन [0: 0] ट्रिक नहीं किया।
jsh

11
sys.path[0:0] = ['/foo']
केविन एडवर्ड्स

6
Explicit is better than implicit.तो sys.path.insert(0, ...)इसके बजाय क्यों नहीं sys.path[0:0]?
विंकलेरर

8

मेरा मानना ​​है कि आप निर्दिष्ट मॉड्यूल का उपयोग कर सकते हैं imp.find_module()और imp.load_module()लोड कर सकते हैं । आपको पथ के मॉड्यूल नाम को विभाजित करने की आवश्यकता होगी, अर्थात यदि आप लोड करना चाहते हैं तो आपको करना /home/mypath/mymodule.pyहोगा:

imp.find_module('mymodule', '/home/mypath/')

... लेकिन वह काम पूरा होना चाहिए।


6

आप pkgutilमॉड्यूल का उपयोग कर सकते हैं (विशेष रूप सेwalk_packagesवर्तमान निर्देशिका में संकुल की सूची प्राप्त करने के लिए विधि) का । वहां से importlibआप जो मॉड्यूल चाहते हैं उसे आयात करने के लिए मशीनरी का उपयोग करना तुच्छ है :

import pkgutil
import importlib

packages = pkgutil.walk_packages(path='.')
for importer, name, is_package in packages:
    mod = importlib.import_module(name)
    # do whatever you want with module now, it's been imported!

5

अजगर मॉड्यूल test.py बनाएँ

import sys
sys.path.append("<project-path>/lib/")
from tes1 import Client1
from tes2 import Client2
import tes3

अजगर मॉड्यूल test_check.py बनाएं

from test import Client1
from test import Client2
from test import test3

हम आयातित मॉड्यूल को मॉड्यूल से आयात कर सकते हैं।


4

पायथन 3.4 का यह क्षेत्र समझने के लिए बेहद यातनापूर्ण लगता है! हालाँकि, एक शुरुआत के रूप में क्रिस कालोवे से कोड का उपयोग करके थोड़ी सी हैकिंग के साथ मैं कुछ काम पाने में कामयाब रहा। यहां मूल कार्य है।

def import_module_from_file(full_path_to_module):
    """
    Import a module given the full path/filename of the .py file

    Python 3.4

    """

    module = None

    try:

        # Get module name and path from full path
        module_dir, module_file = os.path.split(full_path_to_module)
        module_name, module_ext = os.path.splitext(module_file)

        # Get module "spec" from filename
        spec = importlib.util.spec_from_file_location(module_name,full_path_to_module)

        module = spec.loader.load_module()

    except Exception as ec:
        # Simple error printing
        # Insert "sophisticated" stuff here
        print(ec)

    finally:
        return module

यह पायथन 3.4 से गैर-अपग्रेड किए गए मॉड्यूल का उपयोग करता प्रतीत होता है। मैं यह समझने का नाटक नहीं करता कि क्यों, लेकिन यह एक कार्यक्रम के भीतर से काम करने लगता है। मैंने पाया कि क्रिस का समाधान कमांड लाइन पर काम करता है, लेकिन एक कार्यक्रम के अंदर से नहीं।


4

मैं यह नहीं कह रहा हूं कि यह बेहतर है, लेकिन पूर्णता के लिए, मैं execफ़ंक्शन का सुझाव देना चाहता था , जो अजगर 2 और 3 दोनों में उपलब्ध है। exec आप वैश्विक दायरे में, या आंतरिक दायरे में मनमाने कोड को निष्पादित करने की अनुमति देते हैं, शब्दकोश के रूप में प्रदान किया गया।

उदाहरण के लिए, यदि आपके पास "/path/to/moduleफ़ंक्शन के साथ " में एक मॉड्यूल संग्रहीत है foo(), तो आप इसे निम्न कार्य करके चला सकते हैं:

module = dict()
with open("/path/to/module") as f:
    exec(f.read(), module)
module['foo']()

इससे यह थोड़ा और स्पष्ट हो जाता है कि आप कोड को गतिशील रूप से लोड कर रहे हैं, और आपको कुछ अतिरिक्त शक्ति प्रदान करता है, जैसे कि कस्टम बिलिन प्रदान करने की क्षमता।

और यदि विशेषताओं के माध्यम से पहुंच हो, तो कुंजी के बजाय आपके लिए महत्वपूर्ण है, आप ग्लोबल्स के लिए एक कस्टम तानाशाह वर्ग को डिज़ाइन कर सकते हैं, जो इस तरह की पहुंच प्रदान करता है, जैसे:

class MyModuleClass(dict):
    def __getattr__(self, name):
        return self.__getitem__(name)

4

दिए गए फ़ाइलनाम से एक मॉड्यूल आयात करने के लिए, आप अस्थायी रूप से पथ का विस्तार कर सकते हैं, और अंत में ब्लॉक संदर्भ में सिस्टम पथ को पुनर्स्थापित कर सकते हैं :

filename = "directory/module.py"

directory, module_name = os.path.split(filename)
module_name = os.path.splitext(module_name)[0]

path = list(sys.path)
sys.path.insert(0, directory)
try:
    module = __import__(module_name)
finally:
    sys.path[:] = path # restore

3

यह काम करना चाहिए

path = os.path.join('./path/to/folder/with/py/files', '*.py')
for infile in glob.glob(path):
    basename = os.path.basename(infile)
    basename_without_extension = basename[:-3]

    # http://docs.python.org/library/imp.html?highlight=imp#module-imp
    imp.load_source(basename_without_extension, infile)

4
एक अधिक सामान्य तरीका विस्तार बाहर कटौती करने के लिए है: name, ext = os.path.splitext(os.path.basename(infile))। आपका तरीका काम करता है क्योंकि पिछले .py एक्सटेंशन के लिए प्रतिबंध। साथ ही, आपको संभवतः मॉड्यूल को कुछ चर / शब्दकोश प्रविष्टि में आयात करना चाहिए।
रेनेसाक

3

अगर हमारे पास एक ही प्रोजेक्ट की स्क्रिप्ट्स हैं, लेकिन अलग-अलग डायरेक्टरी के साधनों में, हम इस समस्या को निम्न विधि से हल कर सकते हैं।

इस स्थिति utils.pyमें हैsrc/main/util/

import sys
sys.path.append('./')

import src.main.util.utils
#or
from src.main.util.utils import json_converter # json_converter is example method

2

मैंने एक पैकेज बनाया है जो आपके impलिए उपयोग करता है। मैं इसे कॉल करता हूं import_fileऔर इसी तरह इसका उपयोग किया जाता है:

>>>from import_file import import_file
>>>mylib = import_file('c:\\mylib.py')
>>>another = import_file('relative_subdir/another.py')

आप इसे प्राप्त कर सकते हैं:

http://pypi.python.org/pypi/import_file

या कि

http://code.google.com/p/import-file/


1
os.chdir? (टिप्पणी को अनुमोदित करने के लिए न्यूनतम वर्ण)।
नौकाचौक

मैंने सारा दिन एक आयातकर्ता को उत्पन्न किए गए pyinstaller में आयात बग का निवारण करने में बिताया है। अंत में यही एक चीज है जिसने मेरे लिए काम किया। इसे बनाने के लिए बहुत बहुत धन्यवाद!
frakman1

2

रनटाइम पर आयात पैकेज मॉड्यूल (पायथन नुस्खा)

http://code.activestate.com/recipes/223972/

###################
##                #
## classloader.py #
##                #
###################

import sys, types

def _get_mod(modulePath):
    try:
        aMod = sys.modules[modulePath]
        if not isinstance(aMod, types.ModuleType):
            raise KeyError
    except KeyError:
        # The last [''] is very important!
        aMod = __import__(modulePath, globals(), locals(), [''])
        sys.modules[modulePath] = aMod
    return aMod

def _get_func(fullFuncName):
    """Retrieve a function object from a full dotted-package name."""

    # Parse out the path, module, and function
    lastDot = fullFuncName.rfind(u".")
    funcName = fullFuncName[lastDot + 1:]
    modPath = fullFuncName[:lastDot]

    aMod = _get_mod(modPath)
    aFunc = getattr(aMod, funcName)

    # Assert that the function is a *callable* attribute.
    assert callable(aFunc), u"%s is not callable." % fullFuncName

    # Return a reference to the function itself,
    # not the results of the function.
    return aFunc

def _get_class(fullClassName, parentClass=None):
    """Load a module and retrieve a class (NOT an instance).

    If the parentClass is supplied, className must be of parentClass
    or a subclass of parentClass (or None is returned).
    """
    aClass = _get_func(fullClassName)

    # Assert that the class is a subclass of parentClass.
    if parentClass is not None:
        if not issubclass(aClass, parentClass):
            raise TypeError(u"%s is not a subclass of %s" %
                            (fullClassName, parentClass))

    # Return a reference to the class itself, not an instantiated object.
    return aClass


######################
##       Usage      ##
######################

class StorageManager: pass
class StorageManagerMySQL(StorageManager): pass

def storage_object(aFullClassName, allOptions={}):
    aStoreClass = _get_class(aFullClassName, StorageManager)
    return aStoreClass(allOptions)

2

लिनक्स में, निर्देशिका में एक प्रतीकात्मक लिंक जोड़ने से आपकी अजगर स्क्रिप्ट स्थित है।

अर्थात:

ln -s /absolute/path/to/module/module.py /absolute/path/to/script/module.py

/absolute/path/to/script/module.pycयदि आप सामग्री बदलते हैं तो अजगर इसे बनाएगा और अपडेट करेगा/absolute/path/to/module/module.py

फिर mypythonscript.py में निम्नलिखित को शामिल करें

from module import *

1
यह मेरे द्वारा उपयोग की गई हैक है, और इसने मुझे कुछ समस्याओं का कारण बनाया है। अधिक दर्दनाक लोगों में से एक यह था कि आईडीईए में एक मुद्दा है जहां यह लिंक के भीतर से परिवर्तित कोड को पिक नहीं करता है, लेकिन फिर भी जो वह सोचता है उसे बचाने का प्रयास करता है। एक दौड़ की स्थिति जहां अंतिम को बचाना है वह चिपक जाती है ... मैंने इस वजह से एक सभ्य राशि खो दी।
गृप

@Gripp सुनिश्चित नहीं है कि अगर मैं आपके मुद्दे को समझ रहा हूं, लेकिन मैं अक्सर (लगभग विशेष रूप से) अपने डेस्कटॉप से ​​SFTP के माध्यम से एक साइबर सर्वर जैसे एक क्लाइंट के साथ CyberDuck, और उस मामले में भी कोशिश करने के लिए एक बुरा विचार है संपादित करें और सिम्लिंक की गई फ़ाइल को संपादित करें, इसके बजाय मूल फ़ाइल को संपादित करने के लिए अधिक सुरक्षित है। आप इनमें से कुछ मुद्दों का उपयोग करके gitऔर जाँच करके git statusदेख सकते हैं कि स्क्रिप्ट में आपके परिवर्तन वास्तव में इसे स्रोत दस्तावेज़ में वापस ला रहे हैं और ईथर में खो नहीं रहे हैं।
user5359531

2

मैंने importlibमॉड्यूल के आधार पर अपना स्वयं का वैश्विक और पोर्टेबल आयात फ़ंक्शन लिखा है :

  • दोनों मॉड्यूल को एक सबमॉड्यूल के रूप में आयात करने और एक मॉड्यूल की सामग्री को मूल मॉड्यूल (या ग्लोबल्स में अगर कोई माता-पिता मॉड्यूल नहीं है) आयात करने में सक्षम हो।
  • फ़ाइल नाम में अवधि वर्णों के साथ मॉड्यूल आयात करने में सक्षम हो।
  • किसी भी एक्सटेंशन के साथ मॉड्यूल आयात करने में सक्षम हो।
  • एक्सटेंशन के बिना फ़ाइल नाम के बजाय एक सबमॉड्यूल के लिए एक स्टैंडअलोन नाम का उपयोग करने में सक्षम हो जो डिफ़ॉल्ट रूप से है।
  • पहले से आयात किए गए मॉड्यूल के आधार पर sys.pathया कभी खोज पथ संग्रहण पर निर्भर आयात आदेश को परिभाषित करने में सक्षम हो ।

उदाहरण निर्देशिका संरचना:

<root>
 |
 +- test.py
 |
 +- testlib.py
 |
 +- /std1
 |   |
 |   +- testlib.std1.py
 |
 +- /std2
 |   |
 |   +- testlib.std2.py
 |
 +- /std3
     |
     +- testlib.std3.py

समावेश निर्भरता और व्यवस्था:

test.py
  -> testlib.py
    -> testlib.std1.py
      -> testlib.std2.py
    -> testlib.std3.py 

कार्यान्वयन:

नवीनतम परिवर्तन की दुकान: https://sourceforge.net/p/tacklelib/tacklelib/HEAD/tree/trunk/python/tacklelib/tacklelib.py

test.py :

import os, sys, inspect, copy

SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/')
SOURCE_DIR = os.path.dirname(SOURCE_FILE)

print("test::SOURCE_FILE: ", SOURCE_FILE)

# portable import to the global space
sys.path.append(TACKLELIB_ROOT) # TACKLELIB_ROOT - path to the library directory
import tacklelib as tkl

tkl.tkl_init(tkl)

# cleanup
del tkl # must be instead of `tkl = None`, otherwise the variable would be still persist
sys.path.pop()

tkl_import_module(SOURCE_DIR, 'testlib.py')

print(globals().keys())

testlib.base_test()
testlib.testlib_std1.std1_test()
testlib.testlib_std1.testlib_std2.std2_test()
#testlib.testlib.std3.std3_test()                             # does not reachable directly ...
getattr(globals()['testlib'], 'testlib.std3').std3_test()     # ... but reachable through the `globals` + `getattr`

tkl_import_module(SOURCE_DIR, 'testlib.py', '.')

print(globals().keys())

base_test()
testlib_std1.std1_test()
testlib_std1.testlib_std2.std2_test()
#testlib.std3.std3_test()                                     # does not reachable directly ...
globals()['testlib.std3'].std3_test()                         # ... but reachable through the `globals` + `getattr`

testlib.py :

# optional for 3.4.x and higher
#import os, inspect
#
#SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/')
#SOURCE_DIR = os.path.dirname(SOURCE_FILE)

print("1 testlib::SOURCE_FILE: ", SOURCE_FILE)

tkl_import_module(SOURCE_DIR + '/std1', 'testlib.std1.py', 'testlib_std1')

# SOURCE_DIR is restored here
print("2 testlib::SOURCE_FILE: ", SOURCE_FILE)

tkl_import_module(SOURCE_DIR + '/std3', 'testlib.std3.py')

print("3 testlib::SOURCE_FILE: ", SOURCE_FILE)

def base_test():
  print('base_test')

testlib.std1.py :

# optional for 3.4.x and higher
#import os, inspect
#
#SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/')
#SOURCE_DIR = os.path.dirname(SOURCE_FILE)

print("testlib.std1::SOURCE_FILE: ", SOURCE_FILE)

tkl_import_module(SOURCE_DIR + '/../std2', 'testlib.std2.py', 'testlib_std2')

def std1_test():
  print('std1_test')

testlib.std2.py :

# optional for 3.4.x and higher
#import os, inspect
#
#SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/')
#SOURCE_DIR = os.path.dirname(SOURCE_FILE)

print("testlib.std2::SOURCE_FILE: ", SOURCE_FILE)

def std2_test():
  print('std2_test')

testlib.std3.py :

# optional for 3.4.x and higher
#import os, inspect
#
#SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/')
#SOURCE_DIR = os.path.dirname(SOURCE_FILE)

print("testlib.std3::SOURCE_FILE: ", SOURCE_FILE)

def std3_test():
  print('std3_test')

आउटपुट ( 3.7.4):

test::SOURCE_FILE:  <root>/test01/test.py
import : <root>/test01/testlib.py as testlib -> []
1 testlib::SOURCE_FILE:  <root>/test01/testlib.py
import : <root>/test01/std1/testlib.std1.py as testlib_std1 -> ['testlib']
import : <root>/test01/std1/../std2/testlib.std2.py as testlib_std2 -> ['testlib', 'testlib_std1']
testlib.std2::SOURCE_FILE:  <root>/test01/std1/../std2/testlib.std2.py
2 testlib::SOURCE_FILE:  <root>/test01/testlib.py
import : <root>/test01/std3/testlib.std3.py as testlib.std3 -> ['testlib']
testlib.std3::SOURCE_FILE:  <root>/test01/std3/testlib.std3.py
3 testlib::SOURCE_FILE:  <root>/test01/testlib.py
dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', '__file__', '__cached__', 'os', 'sys', 'inspect', 'copy', 'SOURCE_FILE', 'SOURCE_DIR', 'TackleGlobalImportModuleState', 'tkl_membercopy', 'tkl_merge_module', 'tkl_get_parent_imported_module_state', 'tkl_declare_global', 'tkl_import_module', 'TackleSourceModuleState', 'tkl_source_module', 'TackleLocalImportModuleState', 'testlib'])
base_test
std1_test
std2_test
std3_test
import : <root>/test01/testlib.py as . -> []
1 testlib::SOURCE_FILE:  <root>/test01/testlib.py
import : <root>/test01/std1/testlib.std1.py as testlib_std1 -> ['testlib']
import : <root>/test01/std1/../std2/testlib.std2.py as testlib_std2 -> ['testlib', 'testlib_std1']
testlib.std2::SOURCE_FILE:  <root>/test01/std1/../std2/testlib.std2.py
2 testlib::SOURCE_FILE:  <root>/test01/testlib.py
import : <root>/test01/std3/testlib.std3.py as testlib.std3 -> ['testlib']
testlib.std3::SOURCE_FILE:  <root>/test01/std3/testlib.std3.py
3 testlib::SOURCE_FILE:  <root>/test01/testlib.py
dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', '__file__', '__cached__', 'os', 'sys', 'inspect', 'copy', 'SOURCE_FILE', 'SOURCE_DIR', 'TackleGlobalImportModuleState', 'tkl_membercopy', 'tkl_merge_module', 'tkl_get_parent_imported_module_state', 'tkl_declare_global', 'tkl_import_module', 'TackleSourceModuleState', 'tkl_source_module', 'TackleLocalImportModuleState', 'testlib', 'testlib_std1', 'testlib.std3', 'base_test'])
base_test
std1_test
std2_test
std3_test

अजगर में परीक्षण किया गया 3.7.4, 3.2.5,2.7.16

पेशेवरों :

  • दोनों मॉड्यूल को एक सबमॉड्यूल के रूप में आयात कर सकते हैं और किसी मॉड्यूल की सामग्री को मूल मॉड्यूल (या ग्लोबल्स में अगर कोई माता-पिता मॉड्यूल नहीं है) आयात कर सकते हैं।
  • किसी फ़ाइल नाम में अवधियों के साथ मॉड्यूल आयात कर सकते हैं।
  • किसी भी विस्तार मॉड्यूल से किसी भी विस्तार मॉड्यूल आयात कर सकते हैं।
  • एक्सटेंशन के बिना फ़ाइल नाम के बजाय एक सबमॉड्यूल के लिए एक स्टैंडअलोन नाम का उपयोग कर सकते हैं जो डिफ़ॉल्ट रूप से है (उदाहरण के लिए, testlib.std.pyजैसे testlib, testlib.blabla.pyजैसे testlib_blablaऔर इतने पर)।
  • एक sys.pathया कभी खोज पथ भंडारण पर निर्भर नहीं करता है ।
  • कॉल करने के लिए SOURCE_FILEऔर इसके SOURCE_DIRबीच वैश्विक चर को बचाने / पुनर्स्थापित करने की आवश्यकता नहीं है tkl_import_module
  • [ 3.4.xअधिक और अधिक के लिए] नेस्टेड tkl_import_moduleकॉल (उदा: named->local->namedया) में मॉड्यूल नेमस्पेस को मिला सकते हैंlocal->named->local तो)।
  • [के लिए 3.4.xऔर उच्चतर] वैश्विक चर / कार्यों / कक्षाओं को निर्यात कर सकता है जहां से tkl_import_module( tkl_declare_globalफ़ंक्शन के माध्यम से ) आयात किए गए सभी बच्चों के मॉड्यूल के लिए घोषित किया जा रहा है ।

विपक्ष :

  • [के लिए 3.3.xऔर कम] tkl_import_moduleसभी मॉड्यूल में घोषणा करने की आवश्यकता है जो tkl_import_module(कोड दोहराव) को कॉल करता है

अपडेट 1,2 (के लिए)3.4.x केवल और अधिक)

पायथन 3.4 और उच्चतर में आप tkl_import_moduleप्रत्येक मॉड्यूल को घोषित करने की आवश्यकता को बायपास कर सकते हैंtkl_import_module को एक शीर्ष स्तर के मॉड्यूल और फ़ंक्शन एक ही कॉल में सभी बच्चों के मॉड्यूल को इंजेक्ट करेगा (यह एक प्रकार का स्वयं तैनात आयात है)।

अपडेट ३ :

आयात पर समर्थन निष्पादन गार्ड के साथ tkl_source_moduleबैश करने के लिए एनालॉग के रूप में जोड़ा गया समारोह source(आयात के बजाय मॉड्यूल मर्ज के माध्यम से कार्यान्वित)।

अपडेट 4 :

tkl_declare_globalऑटो फ़ंक्शन को सभी बच्चों के मॉड्यूल में एक मॉड्यूल वैश्विक चर निर्यात करने के लिए जोड़ा गया है जहां एक मॉड्यूल वैश्विक चर दिखाई नहीं दे रहा है क्योंकि बाल मॉड्यूल का हिस्सा नहीं है।

अद्यतन ५ :

सभी फ़ंक्शन टैकलिब लाइब्रेरी में चले गए हैं, ऊपर दिए गए लिंक को देखें।


2

एक पैकेज है जो विशेष रूप से इसके लिए समर्पित है:

from thesmuggler import smuggle

# À la `import weapons`
weapons = smuggle('weapons.py')

# À la `from contraband import drugs, alcohol`
drugs, alcohol = smuggle('drugs', 'alcohol', source='contraband.py')

# À la `from contraband import drugs as dope, alcohol as booze`
dope, booze = smuggle('drugs', 'alcohol', source='contraband.py')

यह पायथन संस्करणों (ज्योन और पायपी) में भी परीक्षण किया गया है, लेकिन यह आपके प्रोजेक्ट के आकार के आधार पर ओवरकिल हो सकता है।


1

उत्तर की सूची में इसे जोड़ने से मुझे कुछ भी काम नहीं मिला। यह 3.4 में संकलित (pyd) पायथन मॉड्यूल के आयात की अनुमति देगा:

import sys
import importlib.machinery

def load_module(name, filename):
    # If the Loader finds the module name in this list it will use
    # module_name.__file__ instead so we need to delete it here
    if name in sys.modules:
        del sys.modules[name]
    loader = importlib.machinery.ExtensionFileLoader(name, filename)
    module = loader.load_module()
    locals()[name] = module
    globals()[name] = module

load_module('something', r'C:\Path\To\something.pyd')
something.do_something()

1

काफी सरल तरीका: मान लीजिए कि आप सापेक्ष पथ के साथ फ़ाइल आयात करना चाहते हैं ..//MyLibs/pyfunc.py


libPath = '../../MyLibs'
import sys
if not libPath in sys.path: sys.path.append(libPath)
import pyfunc as pf

लेकिन अगर आप इसे बिना किसी गार्ड के बनाते हैं तो आपको आखिरकार बहुत लंबा रास्ता मिल सकता है


1

पैकेज के importlibबजाय एक सरल समाधान imp(पायथन 2.7 के लिए परीक्षण किया गया, हालांकि यह पायथन 3 के लिए भी काम करना चाहिए):

import importlib

dirname, basename = os.path.split(pyfilepath) # pyfilepath: '/my/path/mymodule.py'
sys.path.append(dirname) # only directories should be added to PYTHONPATH
module_name = os.path.splitext(basename)[0] # '/my/path/mymodule.py' --> 'mymodule'
module = importlib.import_module(module_name) # name space of defined module (otherwise we would literally look for "module_name")

अब आप सीधे इस तरह आयातित मॉड्यूल के नाम स्थान का उपयोग कर सकते हैं:

a = module.myvar
b = module.myfunc(a)

इस समाधान का लाभ यह है कि हमारे कोड में इसका उपयोग करने के लिए हमें उस मॉड्यूल का वास्तविक नाम जानने की आवश्यकता नहीं है जिसे हम आयात करना चाहते हैं । यह उपयोगी है, उदाहरण के लिए, यदि मॉड्यूल का पथ एक विन्यास योग्य तर्क है।


इस तरह आप संशोधित कर रहे हैं sys.path, जो हर उपयोग के मामले में फिट नहीं है।
बेगूसच

@bgusach यह सच हो सकता है, लेकिन यह कुछ मामलों में वांछनीय भी है (एक पैकेज से एक से अधिक मॉड्यूल आयात करते समय sys.path के लिए एक रास्ता जोड़ना चीजों को सरल करता है)। किसी भी दर पर, यदि यह वांछनीय नहीं है, तो कोई तुरंत बाद में कर सकता हैsys.path.pop()
अटैक्सियास

0

यह उत्तर सेबेस्टियन रिताऊ के जवाब का एक पूरक है जो टिप्पणी का जवाब देता है: "लेकिन क्या होगा यदि आपके पास मॉड्यूल का नाम नहीं है?" यह एक त्वरित और गंदा तरीका है, जिसे संभवतया पायथन मॉड्यूल नाम दिया गया है, जिसे एक फ़ाइल नाम दिया गया है - यह केवल पेड़ तक जाता है जब तक कि यह एक __init__.pyफ़ाइल के बिना एक निर्देशिका नहीं पाता है और फिर इसे फ़ाइल नाम में बदल देता है। पायथन 3.4+ के लिए (पाथलिब का उपयोग करता है), जो समझ में आता है क्योंकि Py2 लोग "imp" या अन्य तरीकों के सापेक्ष उपयोग कर सकते हैं:

import pathlib

def likely_python_module(filename):
    '''
    Given a filename or Path, return the "likely" python module name.  That is, iterate
    the parent directories until it doesn't contain an __init__.py file.

    :rtype: str
    '''
    p = pathlib.Path(filename).resolve()
    paths = []
    if p.name != '__init__.py':
        paths.append(p.stem)
    while True:
        p = p.parent
        if not p:
            break
        if not p.is_dir():
            break

        inits = [f for f in p.iterdir() if f.name == '__init__.py']
        if not inits:
            break

        paths.append(p.stem)

    return '.'.join(reversed(paths))

सुधार के लिए निश्चित रूप से संभावनाएं हैं, और वैकल्पिक __init__.pyफ़ाइलों को अन्य परिवर्तनों की आवश्यकता हो सकती है, लेकिन यदि आपके पास __init__.pyसामान्य है, तो यह चाल है।


-1

सबसे अच्छा तरीका, मुझे लगता है, आधिकारिक दस्तावेज से है ( 29.1। Imp - आयात इंटर्ल्स तक पहुँच ):

import imp
import sys

def __import__(name, globals=None, locals=None, fromlist=None):
    # Fast path: see if the module has already been imported.
    try:
        return sys.modules[name]
    except KeyError:
        pass

    # If any of the following calls raises an exception,
    # there's a problem we can't handle -- let the caller handle it.

    fp, pathname, description = imp.find_module(name)

    try:
        return imp.load_module(name, fp, pathname, description)
    finally:
        # Since we may exit via an exception, close fp explicitly.
        if fp:
            fp.close()

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