पायथन वर्ग का आयात कैसे करें जो ऊपर की निर्देशिका में है?


210

मैं एक फ़ाइल में एक वर्ग से विरासत में प्राप्त करना चाहता हूं जो कि वर्तमान में एक से ऊपर एक निर्देशिका में निहित है।

क्या उस फ़ाइल को अपेक्षाकृत आयात करना संभव है?

जवाबों:


176

from ..subpkg2 import mod

पायथन डॉक्स के अनुसार: जब पैकेज पदानुक्रम के अंदर होता है, तो दो डॉट्स का उपयोग करें, जैसा कि आयात विवरण डॉक्टर कहता है:

यह निर्दिष्ट करते समय कि मॉड्यूल को आयात करने के लिए आपको मॉड्यूल के पूर्ण नाम को निर्दिष्ट करने की आवश्यकता नहीं है। जब एक मॉड्यूल या पैकेज दूसरे पैकेज के भीतर निहित होता है, तो पैकेज नाम का उल्लेख किए बिना एक ही शीर्ष पैकेज के भीतर एक रिश्तेदार आयात करना संभव है। निर्दिष्ट मॉड्यूल या पैकेज में अग्रणी डॉट्स का उपयोग करने के बाद fromआप निर्दिष्ट कर सकते हैं कि सटीक नामों को निर्दिष्ट किए बिना वर्तमान पैकेज पदानुक्रम को कैसे पार करना है। एक अग्रणी बिंदु का अर्थ है वर्तमान पैकेज जहां आयात करने वाला मॉड्यूल मौजूद है। दो डॉट्स का मतलब होता है एक पैकेज स्तर । तीन डॉट्स दो स्तरों पर है, आदि। यदि आप पैकेज from . import modमें एक मॉड्यूल से निष्पादित करते हैं pkgतो आप आयात करना समाप्त कर देंगे pkg.mod। यदि आप from ..subpkg2 import modभीतर से निष्पादित करते हैं तो आप pkg.subpkg1आयात करेंगेpkg.subpkg2.mod। रिश्तेदार आयात के लिए विनिर्देश पीईपी 328 के भीतर निहित है ।

पीईपी 328 पूर्ण / सापेक्ष आयात के साथ संबंधित है।


4
up1 = os.path.abspath ('..') sys.path.insert (0, up1)
आर.पी.

पीईपी 328 केवल पायथन-संस्करण दिखाता है: 2.4, 2,5, 2.6। संस्करण 3 को अधिक जानकार आत्माओं के लिए छोड़ दिया गया है।
गिमेल

22
यह त्रुटि को ट्रिगर करता है ValueError: शीर्ष-स्तरीय पैकेज से परे सापेक्ष आयात का प्रयास किया गया
कार्लो

4
ImportError में परिणाम: बिना किसी ज्ञात माता-पिता पैकेज के साथ सापेक्ष आयात का प्रयास किया गया
Rotkiv

115
import sys
sys.path.append("..") # Adds higher directory to python modules path.

1
यह मेरे लिए काम करता है। इसे जोड़ने के बाद, मैं सीधे मूल मॉड्यूल आयात कर सकता हूं, ".." का उपयोग करने की आवश्यकता नहीं है।
इवान हुआ

8
यह केवल काम करता है, मोटे तौर पर बोलना, यदि आवेदन का पीडब्ल्यूडी मूल्य - इसका वर्तमान निर्देशक, माता-पिता का बच्चा है। इसलिए, यहां तक ​​कि अगर यह काम करता है, तो कई प्रकार के प्रणालीगत परिवर्तन इसे नापसंद कर सकते हैं।
फ्लीप

यह मेरे लिए और साथ ही उच्च स्तर के मॉड्यूल के आयात के लिए काम करता है। मैं इसका उपयोग os.chdir ("..") के साथ उच्च स्तर की अन्य फ़ाइलों को लोड करने के लिए करता हूं।
सुरेंद्र श्रेष्ठ

यह गिमेल से उक्त उत्तर के समान त्रुटि को ट्रिगर करता है।
कार्लो

81

@ gimel का उत्तर सही है यदि आप उस पैकेज पदानुक्रम की गारंटी दे सकते हैं जिसका वह उल्लेख करता है। यदि आप नहीं कर सकते हैं - यदि आपकी वास्तविक जरूरत है जैसा कि आपने इसे व्यक्त किया है, विशेष रूप से निर्देशिकाओं से बंधा हुआ है और पैकेजिंग के लिए किसी भी आवश्यक संबंध के बिना - तो आपको __file__मूल निर्देशिका ( os.path.dirnameकॉल की एक जोड़ी) करने के लिए काम करने की आवश्यकता होगी; -), तो (यदि वह निर्देशिका पहले से चालू नहीं है sys.path) अस्थायी रूप से डालें sys.path, के आरंभ में ही __import__dir कहा जाता है, फिर से कहा dir को हटा दें - गन्दा काम वास्तव में, लेकिन, "जब आपको करना चाहिए," (और Pyhon steses प्रोग्रामर को कभी भी ऐसा करने से रोकना नहीं चाहिए जो किया जाना चाहिए - ठीक उसी तरह जैसे कि आईएसओ सी मानक अपने प्रस्तावना में "स्पिरिट ऑफ सी" सेक्शन में कहता है! -)।

यहाँ एक उदाहरण है जो आपके लिए काम कर सकता है:

import sys
import os.path
sys.path.append(
    os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir)))

import module_in_parent_dir

2
यह एक निर्देशिका को जोड़ सकता है जो कि पायथन पैकेज के अंदर होता है और sys.pathइस प्रकार एक ही मॉड्यूल को विभिन्न नामों और सभी संबंधित बग के तहत उपलब्ध कराता है। autopath.py pypy या _preamble.py में ट्विस्ट किया गया, इसे एक खोज मापदंड का उपयोग करके हल करें जो निर्देशिकाओं को ऊपर की ओर ले जाते हुए शीर्ष-स्तरीय पैकेज की पहचान करता है।
JFS

4
आप sys.path.remove(pathYouJustAdded)इस तरह के नए रास्ते को बनाए रखने के लिए जरूरी नहीं कि आयात के बाद आप कुछ करना चाहें ।
माथियास

35

एक निर्देशिका से आयात मॉड्यूल जो वर्तमान निर्देशिका से ठीक एक स्तर ऊपर है:

from .. import module

38
मुझे मिला: शीर्ष-स्तरीय पैकेज से परे सापेक्ष आयात का प्रयास :(
रिकार्डो

25
उपयोग करने में from .. import module मुझे त्रुटि मिली है मूल्य : सिफारिश का पालन करके गैर-पैकेज में संबंधित आयात का प्रयास किया गया
user3428154

4

एक मॉड्यूल को कैसे लोड किया जाए जो एक निर्देशिका है

प्रस्तावना: मैंने अजगर के पारिस्थितिकी तंत्र में लोगों की आसानी से मदद करने की आशा के साथ पिछले उत्तर का पर्याप्त पुनर्लेखन किया, और उम्मीद है कि अजगर की आयात प्रणाली के साथ सभी को सफलता का सबसे अच्छा बदलाव दे।

यह एक पैकेज के भीतर रिश्तेदार आयात को कवर करेगा , जो मुझे लगता है कि ओपी के सवाल का सबसे संभावित मामला है।

अजगर एक मॉड्यूलर प्रणाली है

यही कारण है कि हम लिखने के import fooबजाय मूल नामस्थान से एक मॉड्यूल "फू" लोड करने के लिए लिखते हैं:

foo = dict();  # please avoid doing this
with open(os.path.join(os.path.dirname(__file__), '../foo.py') as foo_fh:  # please avoid doing this
    exec(compile(foo_fh.read(), 'foo.py', 'exec'), foo)  # please avoid doing this

पायथन एक फाइल-सिस्टम के लिए युग्मित नहीं है

यही कारण है कि हम वातावरण में अजगर को एम्बेड कर सकते हैं जहां एक आभासी एक प्रदान किए बिना डिफैक्टो फाइलसिस्टम नहीं है, जैसे कि जेयॉन।

एक फाइलसिस्टम से डिकॉउप होने के कारण आयात को लचीला बनाया जा सकता है, यह डिजाइन आर्काइव / जिप फाइल, इंपोर्ट सिंगलेट्स, बाईटेकोड कैशिंग, सेफी एक्सटेंशन, यहां तक ​​कि रिमोट कोड डेफिनिशन लोडिंग जैसी चीजों के लिए अनुमति देता है।

तो अगर आयात एक फाइल सिस्टम के लिए युग्मित नहीं हैं, तो "वन डायरेक्टरी अप" का क्या मतलब है? हमें कुछ अनुमानों को चुनना होगा लेकिन हम ऐसा कर सकते हैं, उदाहरण के लिए, जब एक पैकेज के भीतर काम करते हैं, तो कुछ आंकड़ों को पहले से ही परिभाषित किया गया है जो सापेक्ष आयात को समान.foo..foo बनाता है और उसी पैकेज के भीतर काम करता है। ठंडा!

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

अजगर का आयात उदाहरण कुछ इस तरह दिखता है:

import importlib.util
import sys

# For illustrative purposes.
file_path = os.path.join(os.path.dirname(__file__), '../foo.py')
module_name = 'foo'

foo_spec = importlib.util.spec_from_file_location(module_name, file_path)
# foo_spec is a ModuleSpec specifying a SourceFileLoader
foo_module = importlib.util.module_from_spec(foo_spec)
sys.modules[module_name] = foo_module
foo_spec.loader.exec_module(foo_module)

foo = sys.modules[module_name]
# foo is the sys.modules['foo'] singleton

पैकेजिंग

आधिकारिक तौर पर यहां एक बेहतरीन उदाहरण परियोजना उपलब्ध है: https://github.com/pypa/sampleproject

एक अजगर पैकेज आपके स्रोत कोड के बारे में जानकारी का एक संग्रह है, जो अन्य उपकरणों को सूचित कर सकता है कि आपके स्रोत कोड को अन्य कंप्यूटरों में कैसे कॉपी किया जाए, और अपने स्रोत कोड को उस सिस्टम के पथ में कैसे एकीकृत किया जाए ताकि import fooअन्य कंप्यूटरों के लिए काम हो (दुभाषिया की परवाह किए बिना) होस्ट ऑपरेटिंग सिस्टम, आदि)

निर्देशिका संरचना

fooकुछ निर्देशिका में अधिमानतः एक पैकेज का नाम है , (अधिमानतः एक खाली निर्देशिका)।

some_directory/
    foo.py  # `if __name__ == "__main__":`  lives here

मेरी प्राथमिकता setup.pyसिबलिंग के रूप में बनाना है foo.py, क्योंकि यह setup.py फ़ाइल को सरल बनाता है, हालाँकि, आप यदि आप चाहें तो डिफ़ॉल्ट रूप से सब कुछ बदलने के लिए कॉन्फ़िगरेशन को लिख सकते हैं / रीडायरेक्ट कर सकते हैं; उदाहरण के लिए foo.pyएक "src /" निर्देशिका के तहत डालना कुछ लोकप्रिय है, यहां कवर नहीं किया गया है।

some_directory/
    foo.py
    setup.py

#!/usr/bin/env python3
# setup.py

import setuptools

setuptools.setup(
    name="foo",
    ...
    py_modules=['foo'],
)

python3 -m pip install --editable ./  # or path/to/some_directory/

"संपादन योग्य" उर्फ -eफिर से फिर से इस निर्देशिका में स्रोत फ़ाइलों को लोड करने के लिए आयात करने वाली मशीनरी को पुनर्निर्देशित करेगा, बजाय मौजूदा सटीक फाइलों को इंस्टॉल-एनवायरनमेंट लाइब्रेरी में कॉपी करने के लिए। यह एक डेवलपर की मशीन पर व्यवहार संबंधी मतभेद भी पैदा कर सकता है, अपने कोड का परीक्षण करना सुनिश्चित करें! वहाँ पाइप के अलावा अन्य उपकरण हैं, हालांकि मैं सुझाव देता हूँ कि पाइप एक परिचयात्मक हो :)

मैं एक मॉड्यूल (एकल ".py" फ़ाइल) के बजाय fooएक "पैकेज" (एक निर्देशिका युक्त __init__.py) बनाना पसंद करता हूं , दोनों "पैकेज" और "मॉड्यूल" को रूट नेमस्पेस में लोड किया जा सकता है, मॉड्यूल नेस्टेड नेमस्पेस के लिए अनुमति देते हैं, यदि हम "रिश्तेदार एक निर्देशिका को" आयात करना चाहते हैं तो यह सहायक है।

some_directory/
    foo/
        __init__.py
    setup.py

#!/usr/bin/env python3
# setup.py

import setuptools

setuptools.setup(
    name="foo",
    ...
    packages=['foo'],
)

मैं भी एक बनाने के लिए करना foo/__main__.pyहै, यह एक मॉड्यूल के रूप में पैकेज निष्पादित करने के लिए अजगर, जैसे की अनुमति देता है python3 -m fooनिष्पादित करेंगे foo/__main__.pyके रूप में __main__

some_directory/
    foo/
        __init__.py
        __main__.py  # `if __name__ == "__main__":`  lives here, `def main():` too!
    setup.py

#!/usr/bin/env python3
# setup.py

import setuptools

setuptools.setup(
    name="foo",
    ...
    packages=['foo'],
    ...
    entry_points={
        'console_scripts': [
            # "foo" will be added to the installing-environment's text mode shell, eg `bash -c foo`
            'foo=foo.__main__:main',
        ]
    },
)

कुछ और मॉड्यूल के साथ इसे बाहर निकाल दें: मूल रूप से, आपके पास एक निर्देशिका संरचना हो सकती है जैसे:

some_directory/
    bar.py           # `import bar`
    foo/
        __init__.py  # `import foo`
        __main__.py
        baz.py       # `import foo.baz
        spam/           
            __init__.py  # `import foo.spam`
            eggs.py      # `import foo.spam.eggs`
    setup.py

setup.py पारंपरिक रूप से स्रोत कोड के बारे में मेटाडेटा जानकारी रखता है, जैसे:

  • "install_requires" नाम से स्थापित करने के लिए कौन सी निर्भरता आवश्यक है
  • पैकेज प्रबंधन के लिए किस नाम का उपयोग किया जाना चाहिए ("नाम स्थापित करें / अनइंस्टॉल करें"), मेरा सुझाव है कि यह हमारे मामले में आपके प्राथमिक अजगर पैकेज नाम से मेल खाता है foo, हालांकि हाइफ़न के लिए अंडरस्कोर को लोकप्रिय बनाना लोकप्रिय है
  • लाइसेंस की जानकारी
  • परिपक्वता टैग (अल्फा / बीटा / आदि),
  • दर्शकों के टैग (डेवलपर्स के लिए, मशीन सीखने के लिए, आदि),
  • एकल पृष्ठ प्रलेखन सामग्री (एक README की तरह),
  • शेल के नाम (आप जो उपयोगकर्ता के नाम पर टाइप करते हैं जैसे कि bash, या नाम जो आपको ग्राफिकल यूजर शेल में एक स्टार्ट मेनू की तरह मिलते हैं),
  • अजगर मॉड्यूल की एक सूची इस पैकेज स्थापित करेगा (और स्थापना रद्द)
  • डिफैक्टो "रन टेस्ट" एंट्री पॉइंट python ./setup.py test

इसका बहुत विस्तार, यह भी मक्खी पर सी एक्सटेंशन संकलित कर सकता है अगर एक स्रोत मॉड्यूल एक विकास मशीन पर स्थापित किया जा रहा है। हर दिन के उदाहरण के लिए मैं PYPA नमूना रिपॉजिटरी के setup.py की सलाह देता हूं

यदि आप एक बिल्ड विरूपण साक्ष्य को जारी कर रहे हैं, उदाहरण के लिए कोड की एक प्रति जो लगभग समान कंप्यूटरों को चलाने के लिए है, तो एक आवश्यकताएँ। Txt फ़ाइल सटीक निर्भरता की जानकारी स्नैपशॉट के लिए एक लोकप्रिय तरीका है, जहां "install_requires" न्यूनतम कैप्चर करने का एक अच्छा तरीका है अधिकतम संगत संस्करण। हालांकि, यह देखते हुए कि लक्ष्य मशीनें वैसे भी लगभग समान हैं, मैं अत्यधिक एक पूरे अजगर उपसर्ग का टारबॉल बनाने की सलाह देता हूं। यह मुश्किल हो सकता है, यहां तक ​​पहुंचने में बहुत विस्तृत है। की जाँच करें pip installके --targetसुराग के लिए विकल्प, या virtualenv उर्फ venv।

उदाहरण के लिए वापस

कैसे एक फ़ाइल को एक निर्देशिका आयात करने के लिए:

Foo / spam / eggs.py से, अगर हम foo / baz से कोड चाहते थे, तो हम इसके पूर्ण नाम पते द्वारा पूछ सकते हैं:

import foo.baz

यदि हम भविष्य में कुछ अन्य रिश्तेदार bazकार्यान्वयन के साथ अंडाशय को किसी अन्य निर्देशिका में स्थानांतरित करने की क्षमता आरक्षित करना चाहते थे , तो हम एक रिश्तेदार आयात का उपयोग कर सकते हैं:

import ..baz

-5

अजगर एक मॉड्यूलर प्रणाली है

अजगर एक फाइल सिस्टम पर भरोसा नहीं करता है

अजगर कोड को मज़बूती से लोड करने के लिए, उस कोड को एक मॉड्यूल में रखें, और उस मॉड्यूल को अजगर की लाइब्रेरी में स्थापित किया जाए।

स्थापित मॉड्यूल हमेशा शीर्ष स्तर के नाम स्थान से लोड किए जा सकते हैं import <name>


आधिकारिक तौर पर यहां एक बेहतरीन नमूना परियोजना उपलब्ध है: https://github.com/pypa/sampleproject

मूल रूप से, आपके पास एक निर्देशिका संरचना हो सकती है जैसे:

the_foo_project/
    setup.py  

    bar.py           # `import bar`
    foo/
      __init__.py    # `import foo`

      baz.py         # `import foo.baz`

      faz/           # `import foo.faz`
        __init__.py
        daz.py       # `import foo.faz.daz` ... etc.

अपने setuptools.setup()में घोषित करना सुनिश्चित करें setup.py,

आधिकारिक उदाहरण: https://github.com/pypa/sampleproject/blob/master/setup.py

हमारे मामले में हम शायद निर्यात करना चाहते हैं bar.pyऔर foo/__init__.py, मेरा संक्षिप्त उदाहरण:

setup.py

#!/usr/bin/env python3

import setuptools

setuptools.setup(
    ...
    py_modules=['bar'],
    packages=['foo'],
    ...
    entry_points={}, 
        # Note, any changes to your setup.py, like adding to `packages`, or
        # changing `entry_points` will require the module to be reinstalled;
        # `python3 -m pip install --upgrade --editable ./the_foo_project
)

अब हम अपने मॉड्यूल को अजगर लाइब्रेरी में स्थापित कर सकते हैं; पाइप के साथ, आप the_foo_projectसंपादन मोड में अपने अजगर पुस्तकालय में स्थापित कर सकते हैं , इसलिए हम वास्तविक समय में इस पर काम कर सकते हैं

python3 -m pip install --editable=./the_foo_project

# if you get a permission error, you can always use 
# `pip ... --user` to install in your user python library

अब किसी भी अजगर के संदर्भ से, हम अपने साझा py_modules और पैकेज लोड कर सकते हैं

foo_script.py

#!/usr/bin/env python3

import bar
import foo

print(dir(bar))
print(dir(foo))

2
उल्लेख करना चाहिए कि मैं हमेशा अपने मॉड्यूल को स्थापित करता हूं जब मैं इसके साथ काम करता हूं pip install --edit foo, लगभग हमेशा एक वर्चुअन के अंदर। मैं लगभग एक मॉड्यूल को कभी नहीं लिखता हूं जिसे स्थापित करने का इरादा नहीं है। अगर मुझे कुछ गलत लगता है तो मैं जानना चाहूंगा।
थोरसुमोनर

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