मूल फ़ोल्डर से मॉड्यूल आयात करना


624

मैं पायथन 2.5 चला रहा हूं।

यह मेरा फ़ोल्डर ट्री है:

ptdraft/
  nib.py
  simulations/
    life/
      life.py

(मेरे पास भी है __init__.py प्रत्येक फ़ोल्डर में पठनीयता के लिए छोड़ा गया है)

मैं nibमॉड्यूल के अंदर से मॉड्यूल कैसे आयात करूं life? मुझे उम्मीद है कि यह sys.path के साथ छेड़छाड़ के बिना करना संभव है।

नोट: मुख्य मॉड्यूल चलाया जा रहा है जो ptdraftफ़ोल्डर में है।


1
आपकी PYTHONPATH सेटिंग क्या है?
S.Lott

2
रॉस: मैंने वहाँ देखा। मुझे इसके बारे में क्या करना चाहते हैं? मेरे पास पहले से ही ए __init__.py। एस.लॉट: मुझे नहीं पता कि कैसे जांचना है ...
राम रचूम

4
खोल से $ PYTHONPATH गूंज; आयात sys; अजगर के भीतर से sys.path प्रिंट करें। docs.python.org/tutorial/…
S.Lott

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

3
मैं दृढ़ता से पिछले सभी sys.pathया PYTHONPATHउत्तरों को छोड़ने और np8 के उत्कृष्ट उत्तर की जांच करने की सलाह देता हूं । हाँ, यह एक लंबा पढ़ा है। हां, यह बहुत काम की लगती है। लेकिन इसका एक ही जवाब है कि वास्तव में समस्या को सही और सफाई से हल करना है।
अरण-फे

जवाबों:


118

ऐसा लगता है कि समस्या मूल निर्देशिका या इस तरह की किसी चीज के मॉड्यूल से संबंधित नहीं है।

आपको उस निर्देशिका को जोड़ना होगा जिसमें सम्‍मिलित है ptdraft PYTHONPATH है

आपने कहा कि import nibआपके साथ काम किया, इसका मतलब है कि आपने ptdraftPYTHONPATH में खुद को जोड़ा (अपने माता-पिता को नहीं)।


15
यदि आप बहुत सारे पैकेजों के साथ काम कर रहे हैं जो कभी भी पुन: उपयोग नहीं होने जा रहे हैं, तो सब कुछ पाइथनथ में जोड़ना एक अच्छा उपाय नहीं है।
जेसन चेंग

@ जैसनचेंग: फिर वे पैकेज क्यों हैं ?
डेविस हेरिंग

6
मेरे लिए इस जवाब ने काम किया है। हालांकि, इसे और अधिक स्पष्ट करने के लिए, प्रक्रिया है import sysऔर फिरsys.path.append("..\<parent_folder>")
बीसीजुआन

603

आप सापेक्ष आयातों का उपयोग कर सकते हैं (अजगर> = 2.5):

from ... import nib

(पायथन 2.5 में नया क्या है) PEP 328: निरपेक्ष और सापेक्ष आयात

संपादित करें : एक और डॉट जोड़ा गया। ' दो पैकेज ऊपर जाने के लिए


177
ValueError: Attempted relative import in non-package
एंडोलिथ

18
@endolith: आप एक पैकेज में रहना होगा यानी, आप एक होना आवश्यक है init .py फ़ाइल।
kirbyfan64sos

31
टॉपलेवल पैकेज से परे संबंधित आयात का प्रयास किया गया
उपयोगकर्ता

291
और भी सटीक होने के लिए, आपको एक __init__.pyफ़ाइल की आवश्यकता है ।
कारा डेनिज़

17
निम्नलिखित उत्तर भी देखें, क्योंकि जोड़ने के __init__.pyलिए केवल एक चीज नहीं है जो आपको करना है: stackoverflow.com/questions/11536764/…
बेन किसान

286

सापेक्ष आयात (के रूप में from .. import mymodule) केवल एक पैकेज में काम करते हैं। 'मायमॉडल' आयात करने के लिए जो आपके वर्तमान मॉड्यूल की मूल निर्देशिका में है:

import os,sys,inspect
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0,parentdir) 

import mymodule

संपादित करें : __file__विशेषता हमेशा नहीं दी जाती है। के बजाय का उपयोग करने काos.path.abspath(__file__) मैंने अब वर्तमान फ़ाइल के फ़ाइल नाम (और पथ) को पुनः प्राप्त करने के लिए निरीक्षण मॉड्यूल का उपयोग करने का सुझाव दिया


97
कुछ छोटा है:sys.path.insert(1, os.path.join(sys.path[0], '..'))
झोलता २२'१३

8
डालने के बजाय sys.path.append () से बचने का कोई कारण?
टायलर

2
@ टायलर - अगर यह कहीं और है तो बात हो सकती है parentdir, लेकिन पहले से निर्दिष्ट पथों में से एक में sys.path, 'मायमॉडल' नाम के साथ एक और मॉड्यूल है। सूची parentdirके पहले तत्व के रूप में सम्मिलित करने का sys.pathआश्वासन देता है कि मॉड्यूल को parentdirइसके बजाय आयात किया जाएगा।
रेमी

5
@ झोलता यदि आप पैकेज के साथ काम नहीं कर रहे हैं, तो आपका सबसे अच्छा समाधान है।
जोनाथन रेनहार्ट

5
@ जहोल्टा महान विचार। sys.path.insert(1, os.path.realpath(os.path.pardir))काम भी करता है।
SpeedCoder5

177

मैंने सिबलिंग पैकेज से आयात के संबंध में भी एक समान उत्तर पोस्ट किया। आप इसे यहाँ देख सकते हैं ।

sys.pathहैक्स के बिना समाधान

सारांश

  • एक फ़ोल्डर में कोड लपेटें (उदाहरण के लिए packaged_stuff)
  • setup.pyस्क्रिप्ट बनाएँ का उपयोग करें जहाँ आप setuptools.setup () का उपयोग करते हैं ।
  • पिप पैकेज को संपादन योग्य अवस्था में स्थापित करता है pip install -e <myproject_folder>
  • का उपयोग कर आयात करें from packaged_stuff.modulename import function_name

सेट अप

मैं प्रश्न में के रूप में एक ही फ़ोल्डर संरचना मान

.
└── ptdraft
    ├── __init__.py
    ├── nib.py
    └── simulations
        ├── __init__.py
        └── life
            ├── __init__.py
            └── life.py

मैं .रूट फ़ोल्डर को कॉल करता हूं , और मेरे मामले में यह स्थित है C:\tmp\test_imports

कदम

1) setup.pyरूट फ़ोल्डर में एक जोड़ें

की सामग्री setup.pyबस हो सकती है

from setuptools import setup, find_packages

setup(name='myproject', version='1.0', packages=find_packages())

मूल रूप से "कोई भी" setup.pyकाम करेगा। यह सिर्फ एक न्यूनतम काम करने का उदाहरण है।

2) एक आभासी वातावरण का उपयोग करें

यदि आप आभासी वातावरण से परिचित हैं, तो एक को सक्रिय करें, और अगले चरण पर जाएं। आभासी वातावरण के उपयोग की बिल्कुल आवश्यकता नहीं है, लेकिन वे वास्तव में लंबे समय में आपकी मदद करेंगे (जब आपके पास 1 से अधिक परियोजना चल रही हो ..)। सबसे बुनियादी चरण हैं (रूट फ़ोल्डर में चलाएँ)

  • वर्चुअल एनवी बनाएं
    • python -m venv venv
  • वर्चुअल एनवी को सक्रिय करें
    • . /venv/bin/activate(लिनक्स) या ./venv/Scripts/activate(विन)

इसके बारे में अधिक जानने के लिए, बस Google "python virtualenv ट्यूटोरियल" या समान। आपको संभवतः किसी भी अन्य कमांड को बनाने, सक्रिय करने और निष्क्रिय करने की आवश्यकता नहीं है।

एक बार जब आप एक आभासी वातावरण बना और सक्रिय कर लेते हैं, तो आपके कंसोल को कोष्ठक में आभासी वातावरण का नाम देना चाहिए

PS C:\tmp\test_imports> python -m venv venv
PS C:\tmp\test_imports> .\venv\Scripts\activate
(venv) PS C:\tmp\test_imports>

3) संपादन योग्य अवस्था में अपनी परियोजना को स्थापित करें

myprojectका उपयोग कर अपने शीर्ष स्तर पैकेज स्थापित करें pip। चाल का उपयोग करने के लिए है-eस्थापित करते समय ध्वज । इस तरह यह एक संपादन योग्य राज्य में स्थापित है, और .py फ़ाइलों के लिए किए गए सभी संपादन स्वचालित रूप से स्थापित पैकेज में शामिल हो जाएंगे।

रूट निर्देशिका में, चलाएँ

pip install -e . (डॉट नोट करें, यह "वर्तमान निर्देशिका" के लिए है)

आप यह भी देख सकते हैं कि इसका उपयोग करके स्थापित किया गया है pip freeze

(venv) PS C:\tmp\test_imports> pip install -e .
Obtaining file:///C:/tmp/test_imports
Installing collected packages: myproject
  Running setup.py develop for myproject
Successfully installed myproject
(venv) PS C:\tmp\test_imports> pip freeze
myproject==1.0

4) प्रीपेंडिंग द्वारा आयात करें mainfolder हर आयात के लिए आयात करें

इस उदाहरण में, mainfolderहोगा ptdraft। इसका यह फायदा है कि आप अन्य मॉड्यूल नामों (अजगर मानक पुस्तकालय या 3 पार्टी मॉड्यूल से) के साथ टकराव में नहीं चलेंगे।


उदाहरण उपयोग

nib.py

def function_from_nib():
    print('I am the return value from function_from_nib!')

life.py

from ptdraft.nib import function_from_nib

if __name__ == '__main__':
    function_from_nib()

भागती हुई जिंदगी

(venv) PS C:\tmp\test_imports> python .\ptdraft\simulations\life\life.py
I am the return value from function_from_nib!

1
यह काम क्यों करता है? यह किसी भी तरह पर्दे के पीछे PYTHONPATH बदल रहा है?
होमेरो एस्मेराल्डो

2
इसके अलावा, यह sys.path दृष्टिकोण का उपयोग करने से बेहतर या अधिक सुरुचिपूर्ण क्यों है?
होमेरो एस्मेराल्डो

5
@HomeroBarrocasSEsmeraldo अच्छे प्रश्न। PYTHONPATH env var अछूता नहीं है। यह साइट-पैकेज में स्थापित होता है , जो पहले से ही है sys.pathऔर जहां कोड आमतौर पर अंतिम उपयोगकर्ताओं द्वारा स्थापित किया जाएगा। यह sys.pathहैक से बेहतर है (और आप पथ हैक की श्रेणी में PYTHONPATH का उपयोग कर शामिल कर सकते हैं) क्योंकि इसका मतलब है कि विकास में कोड आपके लिए उसी तरह का व्यवहार करना चाहिए जैसा कि अन्य उपयोगकर्ताओं के लिए करता है। इसके विपरीत, पथ संशोधनों का उपयोग करते समय, आयात विवरणों को एक अलग तरीके से हल किया जाएगा।
विम

5
यह अब तक, सबसे अच्छा समाधान मैंने पढ़ा है। यह आपकी वर्तमान निर्देशिका के लिए एक लिंक बनाता है ताकि कोड के सभी अपडेट सीधे आपके कार्य निर्देशिका में परिलक्षित हों। घटना में आपको इस प्रविष्टि को हटाने की आवश्यकता है, मैन्युअल रूप से अंडे की फ़ाइल को हटा दें और डिस्ट-पैकेज (यदि आपने पाइप का उपयोग किया है तो साइट-पैकेज) में आसानी से इंस्टॉल से प्रविष्टि को हटा दें।
रक्षित कोठारी

2
अजगर आयात सिरदर्द को और अधिक जटिल क्यों बनाता है? हमें एक सेटअप फ़ाइल, एक आभासी एनवी, एक पाइप स्थापित लिखना होगा? हे भगवान!
इमर्सन जू

68

आप "मॉड्यूल खोज पथ" में OS के आधार पर OS का उपयोग कर सकते हैं जो sys.path में सूचीबद्ध है । तो आप आसानी से निम्नलिखित की तरह मूल निर्देशिका जोड़ सकते हैं

import sys
sys.path.insert(0,'..')

यदि आप पैरेंट-पैरेंट डायरेक्टरी जोड़ना चाहते हैं,

sys.path.insert(0,'../..')

यह अजगर 2 और 3 दोनों में काम करता है।


6
यह वर्तमान निर्देशिका के सापेक्ष है , यहां तक ​​कि मुख्य स्क्रिप्ट वाले भी जरूरी नहीं है।
डेविस हेरिंग

57

यदि आपके मॉड्यूल फ़ोल्डर को PYTHONPATH में जोड़ने से काम नहीं चला, तो आप अपने प्रोग्राम में sys.path सूची को संशोधित कर सकते हैं जहां पायथन दुभाषिया आयात करने के लिए मॉड्यूल की खोज करता है, अजगर प्रलेखन कहता है:

जब स्पैम नामक मॉड्यूल आयात किया जाता है, तो दुभाषिया पहले उस नाम के साथ एक अंतर्निहित मॉड्यूल की खोज करता है। यदि नहीं मिला है, तो यह चर sys.path द्वारा दी गई निर्देशिकाओं की सूची में स्पैमहोम नामक एक फ़ाइल की खोज करता है। sys.path को इन स्थानों से आरंभ किया गया है:

  • इनपुट स्क्रिप्ट (या वर्तमान निर्देशिका) वाली निर्देशिका।
  • PYTHONPATH (निर्देशिका नामों की एक सूची, शेल वैरिएबल PATH के समान सिंटैक्स के साथ)।
  • स्थापना-निर्भर डिफ़ॉल्ट।

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

यह जानते हुए, आप अपने कार्यक्रम में निम्नलिखित कर सकते हैं:

import sys
# Add the ptdraft folder path to the sys.path list
sys.path.append('/path/to/ptdraft/')

# Now you can import your module
from ptdraft import nib
# Or just
import ptdraft

6
आपका उत्तर अच्छा है, लेकिन हमेशा काम नहीं कर सकता है और बहुत पोर्टेबल नहीं है। यदि कार्यक्रम को नए स्थान पर ले जाया गया, /path/to/ptdraftतो उसे संपादित करना होगा। ऐसे समाधान हैं जो फ़ाइल की वर्तमान निर्देशिका को बाहर काम करते हैं और इसे मूल फ़ोल्डर से आयात करते हैं।
एडवर्ड

@ आगे उन तकनीकों क्या हैं?
शुक्लासवाग

1
उदाहरण के लिए @ शुकलस्वाग, उत्तर stackoverflow.com/questions/714063/…
एडवर्ड

50

अजगर 2 के बारे में ज्यादा न जानें
। अजगर 3 में, मूल फ़ोल्डर को निम्न प्रकार से जोड़ा जा सकता है:

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

... और फिर एक से मॉड्यूल आयात करने में सक्षम है


13
यह केवल तभी काम करता है जब आपकी वर्तमान वर्किंग डाइरेक्टरी ऐसी '..'हो जो डायरेक्ट्री के साथ क्वेश्चन में डाइरेक्टरी की ओर ले जाती है।
user5359531

31

यहाँ एक उत्तर है जो सरल है इसलिए आप देख सकते हैं कि यह कैसे काम करता है, छोटा और क्रॉस-प्लेटफ़ॉर्म।
यह केवल अंतर्निहित का उपयोग करता है मॉड्यूल ( os, sysऔर inspect) तो काम करना चाहिए
किसी भी ऑपरेटिंग सिस्टम (ओएस) क्योंकि अजगर कि लिए बनाया गया है पर।

उत्तर के लिए कम कोड - कम लाइनें और चर

from inspect import getsourcefile
import os.path as path, sys
current_dir = path.dirname(path.abspath(getsourcefile(lambda:0)))
sys.path.insert(0, current_dir[:current_dir.rfind(path.sep)])
import my_module  # Replace "my_module" here with the module name.
sys.path.pop(0)

इस से भी कम समय लाइनों के लिए, साथ दूसरी पंक्ति की जगह import os.path as path, sys, inspect,
जोड़ने inspect.के शुरू में getsourcefile(पंक्ति 3) और पहली पंक्ति को हटा दें।
- हालाँकि यह मॉड्यूल के सभी आयात करता है, इसलिए अधिक समय, स्मृति और संसाधनों की आवश्यकता हो सकती है।

मेरे उत्तर के लिए कोड ( लंबा संस्करण )

from inspect import getsourcefile
import os.path
import sys

current_path = os.path.abspath(getsourcefile(lambda:0))
current_dir = os.path.dirname(current_path)
parent_dir = current_dir[:current_dir.rfind(os.path.sep)]

sys.path.insert(0, parent_dir)

import my_module  # Replace "my_module" here with the module name.

यह एक स्टैक ओवरफ्लो उत्तर से एक उदाहरण का उपयोग करता है मैं
पायथन में वर्तमान निष्पादित फ़ाइल का पथ कैसे प्राप्त करूं ?
अंतर्निहित टूल के साथ कोड चलाने का स्रोत (फ़ाइल नाम) खोजने के लिए।

from inspect import getsourcefile  
from os.path import abspath  

अगला, जहाँ भी आप स्रोत फ़ाइल को आप से ढूंढना चाहते हैं, उसका उपयोग करें:

abspath(getsourcefile(lambda:0))

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

कोड में एक मॉड्यूल आयात करने के बाद, sys.path.pop(0)एक नई लाइन पर चलने के लिए एक अच्छा विचार है
जब उस जोड़े गए फ़ोल्डर में एक अन्य नाम के समान मॉड्यूल होता है
जिसे बाद में प्रोग्राम में आयात किया जाता है । आपको आयात से पहले जोड़े गए सूची आइटम को निकालने की आवश्यकता है, अन्य रास्तों की नहीं।
यदि आपका प्रोग्राम अन्य मॉड्यूल आयात नहीं करता है, तो फ़ाइल पथ को हटाना सुरक्षित नहीं है क्योंकि
प्रोग्राम समाप्त होने के बाद (या पायथन शेल को पुनरारंभ करना), sys.pathगायब होने के लिए किया गया कोई भी संपादन ।

एक फ़ाइल नाम चर के बारे में नोट्स

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

कुछ उदाहरण जहां यह काम नहीं करता है ( इस स्टैक ओवरफ्लो प्रश्न से उद्धरण ):

• यह कुछ प्लेटफार्मों पर नहीं पाया जा सकता है • यह कभी-कभी पूर्ण फ़ाइल पथ नहीं है

  • py2exeएक __file__विशेषता नहीं है , लेकिन एक समाधान है
  • जब आप IDLE से चलते हैं तो execute()कोई __file__विशेषता नहीं होती है
  • ओएस एक्स 10.6 जहां मुझे मिलता है NameError: global name '__file__' is not defined

1
मैंने ऐसा किया और sys.path.pop(0)वांछित मॉड्यूल आयात करने के तुरंत बाद नई पथ प्रविष्टि को हटा दिया । हालाँकि, बाद में आयात उस स्थान पर चले गए। उदाहरण के लिए, मेरे पास है app/config, app/toolsऔर app/submodule/config। से submodule, मैं app/आयात करने के लिए सम्मिलित करता हूं tools, फिर हटाता हूं और आयात करने का app/प्रयास करता configहूं, लेकिन मुझे app/configइसके बजाय मिलता है app/submodule/config
user5359531

मुझे पता लगा कि माता-पिता की डायर से एक toolsआयात भी हो रहा था config। इसलिए जब मैंने बाद में sys.path.pop(0); import configअंदर जाने की कोशिश की, तो submoduleपाने की उम्मीद में app/submodule/config, मैं वास्तव में मिल रहा था app/config। जाहिर है कि पायथन वास्तव में sys.pathउस नाम से मेल खाने वाले मॉड्यूल की जाँच करने के बजाय उसी नाम के मॉड्यूल का कैश्ड संस्करण देता है । sys.pathइस मामले में सही तरीके से परिवर्तन किया जा रहा था, पायथन सिर्फ एक ही नाम वाले मॉड्यूल के कारण पहले से लोड होने के कारण इसकी जांच नहीं कर रहा था।
user5359531

मुझे लगता है कि मेरे पास इस मुद्दे का सटीक संदर्भ है: docs.python.org/3/reference/import.html#the-module-cache
उपयोगकर्ता 5359531

5.3.1 से कुछ उपयोगी जानकारी प्रलेखन पृष्ठ पर मॉड्यूल कैश : आयात के दौरान, मॉड्यूल का नाम ऊपर देखा जाता है sys.modules ... sys.modules लेखन योग्य है। कुंजी को हटाने से नामित मॉड्यूल के लिए कैश प्रविष्टि को अमान्य कर दिया जाएगा, जिससे पायथन अपने अगले आयात पर नए सिरे से खोज करेगा। ... हालांकि सावधान रहें, यदि आप मॉड्यूल ऑब्जेक्ट का संदर्भ रखते हैं, तो उसके कैश को अमान्य करें फिर आयात करें, दोनों ऑब्जेक्ट अलग-अलग होंगे। इसके विपरीत, importlib.reload()मॉड्यूल सामग्री का पुन: उपयोग और पुनर्निवेश करेगा ...
एडवर्ड

और भी छोटा os.path.realpath(getsourcefile(lambda:0) + "/../.."):। वर्तमान स्रोत फ़ाइल को दो मूल निर्देशिका प्रतीकों के साथ जोड़ा जाएगा। मैंने उपयोग नहीं os.path.sepकिया getsourcefileथा क्योंकि /विंडोज पर भी उपयोग करके एक स्ट्रिंग लौटाया गया था । realpathपूर्ण पथ (इस मामले में, फ़ाइल नाम, और फिर वर्तमान निर्देशिका) से दो निर्देशिका प्रविष्टियों को पॉप करने का ध्यान रखेगा जो मूल निर्देशिका देता है।
कोबर्न

28

यहाँ अधिक सामान्य समाधान है जिसमें मूल निर्देशिका sys.path (मेरे लिए काम करता है) शामिल है:

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

import os, sys\n sys.path.insert(0,os.path.pardir) एक ही बात है, लेकिन शर्बत :) (टिप्पणियों में कोई पंक्ति नहीं है)
एंटी वीराना

@antiveeranna, अगर आप उपयोग करते os.path.pardirहैं , तो आपको माता-पिता के वास्तविकपथ की प्राप्ति नहीं होगी, जहाँ से आप कॉल कर रहे हैं, उसके सापेक्ष मार्गsys.path.insert()
alvas

1
यह उत्तर उस __file__चर का उपयोग करता है जो अविश्वसनीय हो सकता है (हमेशा पूर्ण फ़ाइल पथ नहीं है, हर ऑपरेटिंग सिस्टम आदि पर काम नहीं करता है) जैसा कि स्टैकऑवरफ़्लो उपयोगकर्ताओं ने अक्सर उल्लेख किया है। इसमें शामिल नहीं होने के जवाब को बदलने से समस्याएं कम होंगी और अधिक क्रॉस-संगत होगी। अधिक जानकारी के लिए, stackoverflow.com/a/33532002/3787376 देखें ।
एडवर्ड

22

मैंने स्क्रिप्ट के मूल निर्देशिका से पैकेज आयात करने के लिए निम्न तरीके से काम किया। उदाहरण में, मैं पैकेज env.pyसे कार्यों को आयात करना चाहूंगा app.db

.
└── my_application
    └── alembic
        └── env.py
    └── app
        ├── __init__.py
        └── db
import os
import sys
currentdir = os.path.dirname(os.path.realpath(__file__))
parentdir = os.path.dirname(currentdir)
sys.path.append(parentdir)

तो, एक अच्छा एक लाइनर:sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
रद्दी

sys.pathसभी को संशोधित करना आमतौर पर एक बुरा विचार है। आप किसी तरह (की जरूरत है जैसे , PYTHONPATH) अपने पुस्तकालय के लिए सुलभ होने के लिए अन्य कोड (या कोई अन्य यह वास्तव में एक पुस्तकालय नहीं है); बस हर समय उपयोग करें!
डेविस हेरिंग

14

ऊपर वर्णित समाधान भी ठीक हैं। इस समस्या का एक और समाधान है

यदि आप शीर्ष स्तर की निर्देशिका से कुछ भी आयात करना चाहते हैं। फिर,

from ...module_name import *

इसके अलावा, यदि आप मूल निर्देशिका से किसी भी मॉड्यूल को आयात करना चाहते हैं। फिर,

from ..module_name import *

इसके अलावा, यदि आप मूल निर्देशिका से किसी भी मॉड्यूल को आयात करना चाहते हैं। फिर,

from ...module_name.another_module import *

इस तरह आप किसी विशेष विधि को आयात कर सकते हैं यदि आप चाहते हैं।


6
ऐसा लगता है जैसे यह होना चाहिए, लेकिन किसी कारण से यह उसी तरह से काम नहीं करता है जैसे sys.path.appendऊपर के हैक्स और मैं इस तरह से अपने काम को आयात नहीं कर सकता। यह वही है जो मैंने पहली बार google पर शुरू करने से पहले करने की कोशिश की थी :) ठीक है, यह थाValueError: attempted relative import beyond top-level package
juzzlin

10

माता-पिता की निर्देशिका तक पहुँचने के लिए मेरे लिए सबसे छोटा और मेरा पसंदीदा ऑन्लाइनर है:

sys.path.append(os.path.dirname(os.getcwd()))

या:

sys.path.insert(1, os.path.dirname(os.getcwd()))

os.getcwd () वर्तमान कामकाजी निर्देशिका का नाम देता है, os.path.dirname (directory_name) पास किए गए निर्देशिका नाम को लौटाता है।

वास्तव में, मेरी राय में पायथन प्रोजेक्ट आर्किटेक्चर को उस तरह से किया जाना चाहिए, जहां चाइल्ड डायरेक्टरी का कोई एक मॉड्यूल पैरेंट डायरेक्टरी के किसी भी मॉड्यूल का उपयोग नहीं करेगा। यदि ऐसा कुछ होता है, तो यह परियोजना के पेड़ के बारे में पुनर्विचार करने के लायक है।

PYTHONPATH सिस्टम वातावरण चर में मूल निर्देशिका को जोड़ने का एक और तरीका है।


2
+1 परियोजना के पुनर्गठन की संभावना का उल्लेख करने के लिए (जैसा कि समस्या में एक हैक को फेंकने का विरोध किया गया है)
semore_1267

यह माता-पिता को नहीं मिलता है, यह वर्तमान मिलता है
रिकी लेवी

9

एक ज्यूपिटर नोटबुक में

जब तक आप जुपिटर नोटबुक में काम कर रहे हैं, तब तक यह छोटा समाधान उपयोगी हो सकता है:

%cd ..
import nib

यह बिना __init__.pyफाइल के भी काम करता है ।

मैंने इसे लिनक्स और विंडोज 7 पर एनाकोंडा 3 के साथ परीक्षण किया।


2
क्या %cd -आयात के बाद इसे जोड़ने का कोई मतलब नहीं होगा , इसलिए नोटबुक की वर्तमान निर्देशिका अपरिवर्तित रहती है।
Dror


5

जब __init__.pyपैलिब लाइब्रेरी (> = पायथॉन 3.4 के साथ शामिल) फाइलों के साथ पैकेज के माहौल में नहीं होता है, तो यह PYTHONPATH को मूल निर्देशिका के पथ को जोड़ने के लिए बहुत संक्षिप्त और सहज बनाता है:

import sys
from pathlib import Path
sys.path.append(str(Path('.').absolute().parent))

क्या इस समस्या को दरकिनार करने के लिए init .py का उपयोग करना संभव है?
कृत्रिम रूप से

4

पिछले उत्तर के रूप में एक ही तरह की शैली - लेकिन कम लाइनों में: पी

import os,sys
parentdir = os.path.dirname(__file__)
sys.path.insert(0,parentdir)

फ़ाइल उस स्थान को लौटाती है जिसमें आप काम कर रहे हैं


मेरे लिए फ़ाइल शामिल पथ के बिना फ़ाइल नाम है । मैं इसे "ipy filename.py" का उपयोग करके चलाता हूं।
कर्टिस यलोप

हाय @CurtisYallop ऊपर दिए गए उदाहरण में हम उस dir को जोड़ रहे हैं जिसमें वह फ़ाइल है [जिसमें हम वर्तमान में हैं] कि अजगर फ़ाइल में है। फ़ाइल नाम के साथ os.path.dirname कॉल को फ़ाइल का पथ वापस करना चाहिए और हमें। पथ में THAT जोड़ रहे हैं और स्पष्ट रूप से फ़ाइल नहीं - HTH के :-)
YFP

आप मान रहे हैं कि __file__ में हमेशा पथ प्लस फ़ाइल शामिल है। कभी-कभी इसमें पथ के बिना केवल फ़ाइल नाम होता है।
कर्टिस येलोप

@CurtisYallop - बिल्कुल नहीं, मैं मान रहा हूं कि फ़ाइल का नाम फ़ाइल है और मैं फ़ाइल के लिए पथ प्राप्त करने के लिए os.path.dirname () का उपयोग कर रहा हूं। क्या आपको इसका उदाहरण काम नहीं आया? मैं ठीक करने के चरण प्यार होता
YFP

1
@CurtisYallop - नहीं मैं नहीं हूँ! मैं कह रहा हूँ कि: प्रिंट / _ / फ़ाइल / _ / आपको "फ़ाइलहोम" के ऊपर आपके उदाहरण में फ़ाइल नाम देगा - मैं फिर कह रहा हूँ कि आप पूर्ण पथ खींचने के लिए os.path.dirname () का उपयोग कर सकते हैं । यदि आप कुछ अजीब स्थान से फोन कर रहे हैं और आप उस संबंधपरक को पसंद करेंगे तो आप आसानी से ओएस मॉड्यूल - जीज़ के माध्यम से अपना काम कर सकते हैं!
YFP

1

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


1
आपका विचार अच्छा है, लेकिन कुछ लोग अपने मॉड्यूल को अपने कोड के साथ बंडल करना चाह सकते हैं - शायद इसे पोर्टेबल बनाने के लिए और site-packagesहर बार जब वे इसे एक अलग कंप्यूटर पर चलाते हैं तो उन्हें अपने मॉड्यूल को लगाने की आवश्यकता नहीं होती है।
एडवर्ड

0

लिनक्स सिस्टम में, आप "जीवन" फ़ोल्डर से nib.py फ़ाइल में सॉफ्ट लिंक बना सकते हैं। फिर, आप बस इसे आयात कर सकते हैं:

import nib
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.