सिबलिंग पैकेज आयात करता है


199

मैंने सिबलिंग आयात और यहां तक ​​कि पैकेज प्रलेखन के बारे में प्रश्नों के माध्यम से पढ़ने की कोशिश की है , लेकिन मुझे अभी तक उत्तर नहीं मिला है।

निम्नलिखित संरचना के साथ:

├── LICENSE.md
├── README.md
├── api
   ├── __init__.py
   ├── api.py
   └── api_key.py
├── examples
   ├── __init__.py
   ├── example_one.py
   └── example_two.py
└── tests
   ├── __init__.py
   └── test_one.py

कैसे examplesऔर testsनिर्देशिका में स्क्रिप्ट apiमॉड्यूल से आयात और कमांडलाइन से चलाया जा सकता है?

इसके अलावा, मैं sys.path.insertहर फ़ाइल के लिए बदसूरत हैक से बचना चाहूंगा । निश्चित रूप से यह पायथन में किया जा सकता है, है ना?


7
मैं सभी sys.pathहैक्स को अतीत से हटाने और एकमात्र वास्तविक समाधान पढ़ने की सलाह देता हूं जो इस प्रकार अब तक (7 साल बाद!) पोस्ट किया गया है।
अरन-फे

1
वैसे, अभी भी एक और अच्छे समाधान के लिए जगह है: निष्पादन योग्य कोड को लाइब्रेरी कोड से अलग करना; ज्यादातर समय एक पैकेज के अंदर एक स्क्रिप्ट के साथ शुरू करने के लिए निष्पादन योग्य नहीं होना चाहिए ।
अरन-फे

यह सवाल और जवाब दोनों के लिए इतना मददगार है। मैं बस उत्सुक हूं, "स्वीकार किए गए उत्तर" कैसे आते हैं, जैसा कि इस मामले में इनाम से सम्मानित नहीं किया गया है?
इंडोमिनस

@ एरन-फी यह इन रिलेटेड इंपोर्ट एरर Q & As में एक अंडररेटेड रिमाइंडर है। मैं इस पूरे समय एक हैक की तलाश में था, लेकिन मुझे पता था कि समस्या से बाहर निकलने के लिए एक आसान तरीका है। यह कहने के लिए नहीं कि यह यहाँ पढ़ने वाले सभी के लिए समाधान है, लेकिन यह एक अच्छा अनुस्मारक है क्योंकि यह कई लोगों के लिए हो सकता है।
कलरफुल

जवाबों:


69

सात साल बाद

जब से मैंने नीचे उत्तर लिखा है, संशोधित sys.pathकरना अभी भी एक त्वरित और गंदा चाल है जो निजी स्क्रिप्ट के लिए अच्छी तरह से काम करता है, लेकिन इसमें कई सुधार हुए हैं

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

तो यह वास्तव में आप क्या करना चाहते हैं पर निर्भर करता है। आपके मामले में, हालाँकि, ऐसा लगता है कि आपका लक्ष्य किसी बिंदु पर एक उचित पैकेज बनाना है, जिसके माध्यम से स्थापित pip -eकरना शायद आपका सबसे अच्छा दांव है, भले ही यह अभी तक सही नहीं है।

पुराना उत्तर

जैसा कि पहले ही कहीं और कहा गया है, भयावह सच्चाई यह है कि आपको भाई-बहन या माता-पिता के पैकेज को मॉड्यूल से आयात करने की अनुमति देने के लिए बदसूरत हैक करना पड़ता है __main__। समस्या पीईपी 366 में विस्तृत है । पीईपी 3122 ने आयात को अधिक तर्कसंगत तरीके से संभालने का प्रयास किया लेकिन गुइडो ने इसे एक खाते से खारिज कर दिया

एकमात्र उपयोग का मामला स्क्रिप्ट को चलाने वाला प्रतीत होता है जो कि एक मॉड्यूल की निर्देशिका के अंदर रहने वाला होता है, जिसे मैंने हमेशा एंटीपैटर्न के रूप में देखा है।

( यहाँ )

हालांकि, मैं इस पैटर्न का उपयोग नियमित रूप से करता हूं

# Ugly hack to allow absolute import from the root folder
# whatever its name is. Please forgive the heresy.
if __name__ == "__main__" and __package__ is None:
    from sys import path
    from os.path import dirname as dir

    path.append(dir(path[0]))
    __package__ = "examples"

import api

यहाँ path[0] आपकी रनिंग स्क्रिप्ट का पैरेंट फोल्डर और dir(path[0])आपका टॉप लेवल फोल्डर है।

मैं अभी भी इसके साथ सापेक्ष आयात का उपयोग नहीं कर पाया हूं, लेकिन यह शीर्ष स्तर (आपके उदाहरण apiके मूल फ़ोल्डर में) से पूर्ण आयात की अनुमति देता है ।


3
आप नहीं है करने के लिए है आप अगर का उपयोग कर एक परियोजना निर्देशिका से चलाने के -mरूप में या आप पैकेज स्थापित करता है, तो (पिप और virtualenv इसे आसान बनाने के)
JFS

2
आपके लिए एआईआई पैकेज को कैसे पता चलता है? जाहिर है, मुझे यह धागा मिला क्योंकि मैं विशेष रूप से pytest और भाई पैकेज आयात करने के साथ इस समस्या में चल रहा हूं।
जूनियरइंटरनेट

1
मेरे दो सवाल हैं, कृपया। 1. आपका पैटर्न __package__ = "examples"मेरे बिना काम करने लगता है । आप इसका उपयोग क्यों करते हैं? 2. किस स्थिति में है __name__ == "__main__"पर __package__नहीं है None?
वास्तविक_पंडा 16

@actual_panda सेटिंग से __packages__मदद मिलती है अगर आप निरपेक्ष पथ चाहते हैं जैसे कि examples.apiiirc को काम करना (लेकिन यह एक लंबा समय है क्योंकि मैंने आखिरी बार ऐसा किया है) और उस पैकेज की जाँच करना कोई भी नहीं है, यह अजीब परिस्थितियों और भविष्यप्रूफिंग के लिए ज्यादातर विफल रहा।
एवपोक

166

Sys.path हैक्स से थक गए?

वहाँ बहुत sys.path.appendसारे उपलब्ध हैं, लेकिन मुझे हाथ में समस्या को हल करने का एक वैकल्पिक तरीका मिला।

सारांश

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

सेट अप

प्रारंभिक बिंदु आपके द्वारा प्रदान की गई फ़ाइल संरचना है, जिसे फ़ोल्डर में लपेटा जाता है myproject

.
└── myproject
    ├── api
       ├── api_key.py
       ├── api.py
       └── __init__.py
    ├── examples
       ├── example_one.py
       ├── example_two.py
       └── __init__.py
    ├── LICENCE.md
    ├── README.md
    └── tests
        ├── __init__.py
        └── test_one.py

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

api.py

परीक्षण के मामले के रूप में, आइए निम्नलिखित का उपयोग करें ।/api/api.py

def function_from_api():
    return 'I am the return value from api.api!'

test_one.py

from api.api import function_from_api

def test_function():
    print(function_from_api())

if __name__ == '__main__':
    test_function()

Test_one चलाने का प्रयास करें:

PS C:\tmp\test_imports> python .\myproject\tests\test_one.py
Traceback (most recent call last):
  File ".\myproject\tests\test_one.py", line 1, in <module>
    from api.api import function_from_api
ModuleNotFoundError: No module named 'api'

इसके अलावा रिश्तेदार आयात की कोशिश कर रहा है:

के प्रयोग from ..api.api import function_from_apiसे परिणाम होगा

PS C:\tmp\test_imports> python .\myproject\tests\test_one.py
Traceback (most recent call last):
  File ".\tests\test_one.py", line 1, in <module>
    from ..api.api import function_from_api
ValueError: attempted relative import beyond top-level package

कदम

  1. मूल स्तर निर्देशिका के लिए एक setup.py फ़ाइल बनाओ

के लिए सामग्री setup.pyहोगी *

from setuptools import setup, find_packages

setup(name='myproject', version='1.0', packages=find_packages())
  1. आभासी वातावरण का उपयोग करें

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

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

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

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

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

और आपका फ़ोल्डर ट्री इस तरह दिखना चाहिए **

.
├── myproject
   ├── api
      ├── api_key.py
      ├── api.py
      └── __init__.py
   ├── examples
      ├── example_one.py
      ├── example_two.py
      └── __init__.py
   ├── LICENCE.md
   ├── README.md
   └── tests
       ├── __init__.py
       └── test_one.py
├── setup.py
└── venv
    ├── Include
    ├── Lib
    ├── pyvenv.cfg
    └── Scripts [87 entries exceeds filelimit, not opening dir]
  1. पाइप संपादन योग्य अवस्था में अपनी परियोजना स्थापित करें

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
  1. myproject.अपने आयात में जोड़ें

ध्यान दें कि आपको myproject.केवल आयात में जोड़ना होगा जो अन्यथा काम नहीं करेगा। setup.py& के बिना काम करने वाले आयात pip installअभी भी ठीक काम करेंगे। नीचे एक उदाहरण देखें।


समाधान का परीक्षण करें

अब, api.pyऊपर बताए गए, और test_one.pyनीचे परिभाषित का उपयोग करके समाधान का परीक्षण करें।

test_one.py

from myproject.api.api import function_from_api

def test_function():
    print(function_from_api())

if __name__ == '__main__':
    test_function()

परीक्षण चल रहा है

(venv) PS C:\tmp\test_imports> python .\myproject\tests\test_one.py
I am the return value from api.api!

* सेप्टोलूलस डॉक्स देखें अधिक वर्बोज़ उदाहरणों के लिए ।

** वास्तव में, आप अपने हार्ड डिस्क पर कहीं भी अपना आभासी वातावरण रख सकते हैं।


13
विस्तृत पोस्ट के लिए धन्यवाद। यहाँ मेरी समस्या है। यदि मैं आपके द्वारा कही गई हर बात को पूरा करता हूं और मैं एक पाइप फ्रीज करता हूं, तो मुझे -e git+https://username@bitbucket.org/folder/myproject.git@f65466656XXXXX#egg=myprojectहल करने के तरीके पर एक पंक्ति आइडिया मिल जाती है ।
एसआई सोम

2
सापेक्ष आयात समाधान काम क्यों नहीं करता है? मुझे आप पर विश्वास है, लेकिन मैं पायथन की जटिल प्रणाली को समझने की कोशिश कर रहा हूं।
जारेड नीलसन

8
किसी के संबंध में कोई समस्या है ModuleNotFoundError? मैंने इन चरणों का पालन करते हुए एक virtualenv में 'myproject' स्थापित किया है, और जब मैं एक व्याख्या सत्र में प्रवेश करता import myprojectहूं और मुझे मिलता है ModuleNotFoundError: No module named 'myproject'? pip list installed | grep myprojectयह दर्शाता है कि यह वहाँ है, निर्देशिका सही है, और दोनों के सत्यापन pipऔर pythonसही होने के लिए सत्यापित हैं।
वोकिंड

2
अरे @ np8, यह काम करता है मैं गलती से venv में और ओएस :) में यह स्थापित किया है, pip list, शो संकुल, जबकि pip freezeशो अजीब नामों अगर ध्वज के साथ स्थापित -e
Grzegorz Krug

3
लगभग 2 घंटे यह जानने की कोशिश करते रहे कि रिश्तेदार आयात कैसे करते हैं, और यह जवाब वही था जो वास्तव में कुछ समझदार था। 👍👍
ग्राहम Lea

43

यहाँ एक और विकल्प है जिसे मैं testsफ़ोल्डर में पायथन फ़ाइलों के शीर्ष पर सम्मिलित करता हूँ :

# Path hack.
import sys, os
sys.path.insert(0, os.path.abspath('..'))

1
+1 वास्तव में सरल है और इसने पूरी तरह से काम किया है। आपको मूल वर्ग को आयात में जोड़ना होगा (उदा। Api.api, example.example_two), लेकिन मैं इसे इस तरह से पसंद करता हूं।
इवान प्लाइस

10
मुझे लगता है कि यह न्यूबाय्स (अपने आप की तरह) का उल्लेख करने लायक है, ..यहां आप उस निर्देशिका के सापेक्ष हैं, जो आप से परीक्षण कर रहे हैं --- उस परीक्षण / उदाहरण फ़ाइल वाली निर्देशिका से नहीं। मैं परियोजना निर्देशिका से निष्पादित कर रहा हूं, और मुझे ./इसके बजाय आवश्यक था। मनाइए कि यह किसी और के लिए सहायक हो।
जोशुआ डेटलर

@JoshDetwiler, हाँ अनुपस्थित। मुझे इस बारे में पता नहीं था। धन्यवाद।
कयाक

1
यह एक घटिया जवाब है। रास्ता हैक करना अच्छा अभ्यास नहीं है; यह निंदनीय है कि अजगर की दुनिया में इसका कितना उपयोग किया जाता है। इस प्रश्न का एक मुख्य बिंदु यह देखना था कि इस तरह के हैक से बचने के दौरान आयात कैसे किया जा सकता है।
jtcotton63

sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))@JoshuaDetwiler
vldbnc

31

आपको इसकी आवश्यकता नहीं है और sys.pathजब तक यह आवश्यक नहीं है, तब तक हैक नहीं करना चाहिए और इस मामले में यह नहीं है। उपयोग:

import api.api_key # in tests, examples

प्रोजेक्ट निर्देशिका से चलाएँ: python -m tests.test_one :।

आपको शायद अंदर चले जाना चाहिए tests(यदि वे एपीआई के unittests हैं) apiऔर python -m api.testसभी परीक्षणों को चलाने के लिए दौड़ते हैं (यह मानते हुए कि वहाँ है __main__.py) या python -m api.test.test_oneचलाने के लिएtest_one इसके बजाय ।

आप इसे (यह पायथन पैकेज नहीं है) __init__.pyसे भी निकाल सकते हैं examplesऔर उदाहरणों को एक virtualenv में चला सकते हैं जहाँ apiसंस्थापित है, जैसे pip install -e .virtualenv में inplace apiपैकेज स्थापित होगा यदि आपके पास उचित है setup.py


@ उत्तर का यह अर्थ नहीं है कि परीक्षण एपीआई परीक्षण हैं, केवल उस अनुच्छेद को छोड़कर जहां यह स्पष्ट रूप से कहा जाता है कि "यदि वे एपीआई के अयोग्य हैं"
jfs

दुर्भाग्य से तब आप रूट डायर से भाग रहे हैं और पाइकार्म अभी भी अपने अच्छे कार्यों के लिए फाइल नहीं ढूँढ रहा है
mhstnsc

@mhstnsc: यह सही नहीं है। python -m api.test.test_oneVirtualenv के सक्रिय होने पर आपको कहीं से भी चलाने में सक्षम होना चाहिए । यदि आप अपने परीक्षणों को चलाने के लिए PyCharm को कॉन्फ़िगर नहीं कर सकते हैं, तो एक नया स्टैक ओवरफ्लो प्रश्न पूछने का प्रयास करें (यदि आप इस विषय पर कोई मौजूदा प्रश्न नहीं खोज सकते हैं)।
18

@jfs मैंने वर्चुअल एनवी पथ को याद किया, लेकिन मैं इस सामान को कभी भी किसी भी निर्देशिका से चलाने के लिए शेलबैंग लाइन से अधिक का उपयोग नहीं करना चाहता। यह PyCharm के साथ चलने के बारे में नहीं है। PyCharm के साथ देवता भी जानते हैं कि उनके पास कार्यों के माध्यम से पूरा होने और कूदने की क्षमता है जो मैं किसी भी समाधान के साथ काम नहीं कर सका।
mhstnsc

@mhstnsc कई मामलों में एक उपयुक्त शेबंग पर्याप्त है (इसे वर्चुअन पायथन बाइनरी को इंगित करें। किसी भी सभ्य पायथन आईडीई को एक virtualenv का समर्थन करना चाहिए।
jfs

9

मेरे पास अभी तक पाइथनोलॉजी की समझ नहीं है, जो किसी सहोदर / रिश्तेदार आयात हैक के बिना असंबंधित परियोजनाओं के बीच कोड साझा करने के उद्देश्य को देखने के लिए आवश्यक है। उस दिन तक, यह मेरा समाधान है। के लिए examplesया testsसामान आयात करने के लिए ..\api, यह इस तरह दिखेगा:

import sys.path
import os.path
# Import from sibling directory ..\api
sys.path.append(os.path.dirname(os.path.abspath(__file__)) + "/..")
import api.api
import api.api_key

यह अभी भी आपको एपीआई मूल निर्देशिका देगा और आपको "/ .." कॉन्सेप्टेशन sys.path.append (os.path.dirname (os.path.dirname (os.path.abspath ( file ))) की आवश्यकता नहीं होगी ) )
कैमिलो सांचेज

4

भाई-बहनों के पैकेज के आयात के लिए, आप [sys.path] [2] मोड के इंसर्ट या एपेंड विधि का उपयोग कर सकते हैं :

if __name__ == '__main__' and if __package__ is None:
    import sys
    from os import path
    sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )
    import api

यह काम करेगा यदि आप अपनी स्क्रिप्ट को निम्नानुसार लॉन्च कर रहे हैं:

python examples/example_one.py
python tests/test_one.py

दूसरी ओर, आप सापेक्ष आयात का भी उपयोग कर सकते हैं:

if __name__ == '__main__' and if __package__ is not None:
    import ..api.api

इस मामले में आपको अपनी स्क्रिप्ट को '-m' तर्क के साथ लॉन्च करना होगा (ध्यान दें, इस मामले में, आपको '.py' एक्सटेंशन देना होगा ):

python -m packageName.examples.example_one
python -m packageName.tests.test_one

बेशक, आप दो दृष्टिकोणों को मिला सकते हैं, ताकि आपकी स्क्रिप्ट किसी भी तरह से काम न करे, इसे कैसे कहा जाता है:

if __name__ == '__main__':
    if __package__ is None:
        import sys
        from os import path
        sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )
        import api
    else:
        import ..api.api

मैं क्लिक फ्रेमवर्क का उपयोग कर रहा था जिसके पास __file__वैश्विक नहीं है इसलिए मुझे निम्नलिखित का उपयोग करना पड़ा: sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0]))))लेकिन यह अब किसी भी निर्देशिका में काम करता है
GammaGames

3

TLDR

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

बस अपने मूल निर्देशिका में एक स्क्रिप्ट बनाएं जो आपके कॉल कर रहे हैं आपके होने के लिए __main__और वहां से सब कुछ चलाने के लिए। आगे की व्याख्या के लिए पढ़ना जारी रखें।

व्याख्या

यह एक नए पथ को एक साथ हैक किए बिना, अतिरिक्त कमांड लाइन आर्गन्स या अपने प्रत्येक कार्यक्रम में अपने भाई-बहनों को पहचानने के लिए कोड जोड़कर पूरा किया जा सकता है।

जैसा कि मेरा मानना ​​है कि यह विफल रहता है, इससे पहले कि कार्यक्रमों का आह्वान किया जा रहा था, जैसा कि उनका __name__सेट है __main__। जब ऐसा होता है तो स्क्रिप्ट को पैकेज के शीर्ष स्तर पर होना स्वीकार किया जाता है और सिबलिंग निर्देशिका में स्क्रिप्ट को पहचानने से इंकार कर दिया जाता है।

हालांकि, निर्देशिका के शीर्ष स्तर के तहत सब कुछ अभी भी शीर्ष स्तर के तहत कुछ भी ईएलएसई को मान्यता देगा । इसका मतलब यह है कि सिर्फ़ निर्देशिकाओं में फ़ाइलों को प्राप्त करने के लिए आपको केवल एक-दूसरे को पहचानने / उपयोग करने के लिए उन्हें अपनी मूल निर्देशिका में स्क्रिप्ट से कॉल करना है।

अवधारणा का सबूत निम्नलिखित संरचना के साथ एक डायर में:

.
|__Main.py
|
|__Siblings
   |
   |___sib1
   |   |
   |   |__call.py
   |
   |___sib2
       |
       |__callsib.py

Main.py निम्नलिखित कोड शामिल हैं:

import sib1.call as call


def main():
    call.Call()


if __name__ == '__main__':
    main()

sib1 / call.py में शामिल है:

import sib2.callsib as callsib


def Call():
    callsib.CallSib()


if __name__ == '__main__':
    Call()

और sib2 / callib.py में शामिल हैं:

def CallSib():
    print("Got Called")

if __name__ == '__main__':
    CallSib()

यदि आप इस उदाहरण को पुन: पेश करते हैं, तो आप देखेंगे कि कॉल करने Main.pyपर "गॉट कॉलेड" प्रिंट होगा, जैसा sib2/callsib.py कि sib2/callsib.pyइसके माध्यम से प्राप्त होने पर भी परिभाषित किया गया है sib1/call.py। हालाँकि अगर कोई सीधे कॉल करता था sib1/call.py(आयातों में उचित परिवर्तन करने के बाद) तो यह एक अपवाद है। भले ही यह अपने मूल निर्देशिका में स्क्रिप्ट द्वारा बुलाए जाने पर काम करता है, लेकिन अगर यह खुद को पैकेज के शीर्ष स्तर पर मानता है तो यह काम नहीं करेगा।


2

मैंने यह दिखाने के लिए एक नमूना परियोजना बनाई कि मैंने इसे कैसे संभाला है, जो वास्तव में एक और sys.path हैक है जैसा कि ऊपर बताया गया है। पायथन सिबलिंग आयात उदाहरण , जो इस पर निर्भर करता है:

if __name__ == '__main__': import os import sys sys.path.append(os.getcwd())

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


यह केवल तभी काम करता है जब आप स्क्रिप्ट की मूल निर्देशिका से चल रहे हों
Evpok

1

आपको यह देखने की जरूरत है कि संबंधित कोड में आयात विवरण कैसे लिखे गए हैं। यदि examples/example_one.pyनिम्नलिखित आयात विवरण का उपयोग करता है:

import api.api

... तो यह सिस्टम पथ में प्रोजेक्ट की रूट डायरेक्टरी की अपेक्षा करता है।

बिना किसी हैक के इसका समर्थन करने का सबसे आसान तरीका (जैसा कि आप इसे डालते हैं) शीर्ष स्तर की निर्देशिका से उदाहरणों को चलाना होगा, जैसे:

PYTHONPATH=$PYTHONPATH:. python examples/example_one.py 

पायथन 2.7.1 के साथ मुझे निम्नलिखित मिला $ python examples/example.py Traceback (most recent call last): File "examples/example.py", line 3, in <module> from api.api import API ImportError: No module named api.api:। मुझे भी साथ मिलता है import api.api
जचविल

मेरा उत्तर अपडेट किया गया ... तुम करते आयात पथ, कि चारों ओर कोई रास्ता नहीं करने के लिए वर्तमान निर्देशिका जोड़ने के लिए।
ए जे।

1

आप उपयोग कर फ़ोल्डर एक बाहरी पुस्तकालय के रूप में भाई की मूल पथ (और इस तरह बुला मॉड्यूल के माता-पिता) जोड़ सकते हैं: बस मामला किसी ग्रहण पर Pydev का उपयोग कर यहाँ अंत में परियोजना> गुण और सेटिंग बाहरी पुस्तकालय बाईं मेनू के तहत Pydev-PYTHONPATH । फिर आप अपने भाई-बहन से आयात कर सकते हैं, जैसे from sibling import some_class


-3

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

जब आप एक फ़ाइल आयात करते हैं, तो पहले दुभाषिया वर्तमान निर्देशिका की जांच करता है और फिर वैश्विक निर्देशिका खोजता है।

अंदर examplesया testsआप कॉल कर सकते हैं:

from ..api import api

मुझे पायथन 2.7.1 के साथ निम्नलिखित मिलता है:Traceback (most recent call last): File "example_one.py", line 3, in <module> from ..api import api ValueError: Attempted relative import in non-package
zachwill

2
ओह, तो आपको __init__.pyशीर्ष स्तर निर्देशिका में एक फ़ाइल जोड़ना चाहिए । अन्यथा पायथन इसे एक मॉड्यूल के रूप में नहीं

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