पायथन: प्रोजेक्ट पदानुक्रम में समान स्तर पर किसी अन्य निर्देशिका से आयात मॉड्यूल


89

मैंने सभी प्रकार के उदाहरण और अन्य समान प्रश्न देखे हैं, लेकिन मुझे ऐसा उदाहरण नहीं मिल रहा है जो मेरे परिदृश्य से बिल्कुल मेल खाता हो। मुझे ऐसा लगता है कि कुल गुंडे यह पूछ रहे हैं क्योंकि बहुत सारे समान प्रश्न हैं, लेकिन मैं अभी इस "सही ढंग से" काम नहीं कर पा रहा हूं। यहाँ मेरी परियोजना है:

user_management  (package)
        |
        |------- __init__.py
        |
        |------- Modules/
        |           |
        |           |----- __init__.py
        |           |----- LDAPManager.py
        |           |----- PasswordManager.py
        |
        |------- Scripts/
        |           |
        |           |----- __init__.py
        |           |----- CreateUser.py
        |           |----- FindUser.py

यदि मैं "CreateUser.py" को मुख्य user_management निर्देशिका में ले जाता हूं, तो मैं आसानी से उपयोग कर सकता हूं: "import Modules.LDAPManager"LDAPManager.py आयात करने के लिए ---। जो मैं नहीं कर सकता (जो मैं करना चाहता हूं), स्क्रिप्ट्स सबफ़ोल्डर में CreateUser.py रखें, और LDAPManager.py आयात करें। मैं उपयोग करके इसे पूरा करने की उम्मीद कर रहा था "import user_management.Modules.LDAPManager.py"। यह काम नहीं करता है। संक्षेप में, मैं पदानुक्रम फ़ाइलों को आसानी से पदानुक्रम में गहराई से देखने के लिए प्राप्त कर सकता हूं, लेकिन मुझे एक निर्देशिका और दूसरी में नीचे संदर्भित करने के लिए पायथन स्क्रिप्ट नहीं मिल सकती है।

ध्यान दें कि मैं अपनी समस्या को हल करने में सक्षम हूं:

sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import Modules.LDAPManager as LDAPManager

मैंने सुना है कि यह बुरा व्यवहार है और हतोत्साहित किया गया है।

स्क्रिप्ट में फ़ाइलों को सीधे क्रियान्वित किया जा करने का इरादा कर रहे हैं (है init भी आवश्यक स्क्रिप्ट में .py?)। मैंने पढ़ा है कि इस स्थिति में, मुझे -m ध्वज के साथ CreateUser.py निष्पादित करना चाहिए। मैंने इस पर कुछ बदलाव करने की कोशिश की है और सिर्फ LDAPManager.py को पहचानने के लिए CreateUser.py प्राप्त करने के लिए प्रतीत नहीं हो सकता है।

जवाबों:


67

यदि मैं CreateUser.pyमुख्य user_management निर्देशिका में जाता हूं, तो मैं आसानी से उपयोग कर सकता हूं: import Modules.LDAPManagerआयात करने के लिए LDAPManager.py --- यह काम करता है।

कृपया, नहीं । इस तरह से LDAPManagerउपयोग किया जाने वाला मॉड्यूल अन्य आयातों के माध्यम से आयातित के समान नहींCreateUser होगा । यह समस्या पैदा कर सकता है जब आपके पास मॉड्यूल में कुछ वैश्विक स्थिति होती है या अचार / अनपिकलिंग के दौरान। आयात से बचें जो केवल इसलिए काम करते हैं क्योंकि मॉड्यूल उसी निर्देशिका में होता है।

जब आपके पास एक पैकेज संरचना होती है, तो आपको चाहिए:

  • रिश्तेदार के आयात का प्रयोग करें, यानी अगर CreateUser.pyमें है Scripts/:

     from ..Modules import LDAPManager
    

    ध्यान दें कि यह PEP 8 द्वारा हतोत्साहित किया गया था (केवल पिछले तनाव को नोट करें ) क्योंकि अजगर के पुराने संस्करण उन्हें बहुत अच्छी तरह से समर्थन नहीं करते थे, लेकिन यह समस्या वर्षों पहले हल हो गई थी। वर्तमान पीईपी 8 के संस्करण है पूर्ण आयात के लिए एक स्वीकार्य विकल्प के रूप में उन्हें सुझाव देते हैं। मैं वास्तव में उन्हें पैकेज के अंदर पसंद करता हूं।

  • संपूर्ण पैकेज नाम ( CreateUser.pyइन Scripts/) का उपयोग करके पूर्ण आयात का उपयोग करें :

     from user_management.Modules import LDAPManager
    

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

इसके अलावा, मुझे यह अजीब लगता Scripts/है कि यह एक सबपैकेज है। क्योंकि एक वास्तविक इंस्टॉलेशन में user_managementमॉड्यूल को डायरेक्टरी site-packagesमें पाया गया lib/(जो भी आपके ओएस में लाइब्रेरी स्थापित करने के लिए उपयोग किया जाता है) के तहत इंस्टॉल किया जाएगा, जबकि स्क्रिप्ट्स को एक bin/डायरेक्टरी के तहत इंस्टॉल किया जाना चाहिए (जो भी आपके ओएस के लिए निष्पादन योग्य हैं)।

वास्तव में मुझे विश्वास है Script/ तहत भी नहीं होना चाहिए user_management। यह उसी स्तर पर होना चाहिए user_management। इस तरह से आपको उपयोग नहीं करना है -m, लेकिन आपको बस यह सुनिश्चित करना है कि पैकेज मिल सकता है (यह फिर से आईडीई को कॉन्फ़िगर करने, पैकेज को सही ढंग से स्थापित करने या PYTHONPATH=. python Scripts/CreateUser.pyसही पथ के साथ स्क्रिप्ट लॉन्च करने के लिए उपयोग करने का मामला है )।


सारांश में, मैं जिस पदानुक्रम का उपयोग करेगा वह है:

user_management  (package)
        |
        |------- __init__.py
        |
        |------- Modules/
        |           |
        |           |----- __init__.py
        |           |----- LDAPManager.py
        |           |----- PasswordManager.py
        |

 Scripts/  (*not* a package)
        |  
        |----- CreateUser.py
        |----- FindUser.py

तब कोड CreateUser.pyऔर FindUser.pyमॉड्यूल आयात करने के लिए पूर्ण आयात का उपयोग करना चाहिए:

from user_management.Modules import LDAPManager

स्थापना के दौरान आप यह सुनिश्चित करते हैं कि निष्पादन के लिए निर्देशिका के अंदर और स्क्रिप्ट्स user_managementकहीं न कहीं समाप्त हो जाती हैं PYTHONPATHताकि वे मॉड्यूल खोजने में सक्षम हों। विकास के दौरान आप या तो आईडीई कॉन्फ़िगरेशन पर निर्भर होते हैं, या आप मूल निर्देशिका को CreateUser.pyजोड़ते हैंScripts/PYTHONPATH (मेरा मतलब उस निर्देशिका से है जिसमें दोनों शामिल हैं user_managementऔर Scripts):

PYTHONPATH=/the/parent/directory python Scripts/CreateUser.py

या आप PYTHONPATHविश्व स्तर पर संशोधित कर सकते हैं ताकि आपको हर बार यह निर्दिष्ट न करना पड़े। यूनिक्स OSes (linux, Mac OS X आदि) पर आप PYTHONPATHबाहरी चर को परिभाषित करने के लिए शेल स्क्रिप्ट में से एक को संशोधित कर सकते हैं , विंडोज पर आपको पर्यावरणीय चर सेटिंग्स को बदलना होगा।


परिशिष्ट मेरा मानना है कि, अगर आप को Python2 उपयोग कर रहे हैं, यह सुनिश्चित डालकर निहित रिश्तेदार आयात से बचने के लिए बनाने के लिए बेहतर है:

from __future__ import absolute_import

अपने मॉड्यूल के शीर्ष पर। इस तरह import X हमेशा toplevel मॉड्यूल आयात करने का मतलब है Xऔर X.pyउसी निर्देशिका (यदि वह निर्देशिका में नहीं है PYTHONPATH) में फ़ाइल आयात करने का प्रयास नहीं करेगा । इस तरह एक रिश्तेदार आयात करने का एकमात्र तरीका स्पष्ट वाक्यविन्यास ( ए) का उपयोग करना हैfrom . import X ) , जो बेहतर है ( स्पष्ट रूप से निहित से बेहतर है )।

यह सुनिश्चित करेगा कि आप कभी भी "फर्जी" निहित रिश्तेदार आयात का उपयोग न करें, क्योंकि ये ImportErrorस्पष्ट रूप से संकेत देंगे कि कुछ गलत है। अन्यथा आप एक मॉड्यूल का उपयोग कर सकते हैं जो कि आपको नहीं लगता कि यह है।


यदि आप रिश्तेदार आयात का उपयोग कर रहे हैं, तो आपको निष्पादित करना चाहिएpython -m user_management.Scripts.CreateUser
मोनोनोक

14

पायथन 2.5 के बाद से, आप उपयोग कर सकते हैं

from ..Modules import LDAPManager

अग्रणी अवधि आपको अपने उत्तराधिकार में एक स्तर "ऊपर" ले जाती है।

आयात के लिए इंट्रा-पैकेज संदर्भों पर पायथन डॉक्स देखें ।


3

"रूट" में __init__.pyआप ए भी कर सकते हैं

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

जो दोनों मॉड्यूल को आयात योग्य बनाना चाहिए।


0

मैंने उन्हीं मुद्दों का सामना किया। इसे हल करने के लिए, मैंने उपयोग किया export PYTHONPATH="$PWD"। हालाँकि, इस मामले में, आपको Scriptsनीचे दिए गए आधार पर आयात को संशोधित करना होगा :

केस 1: यदि आप user_managementडायर में हैं, तो आपको मॉड्यूल आयात करने के scriptsलिए इस शैली from Modules import LDAPManagerका उपयोग करना चाहिए ।

केस 2: आप से बाहर कर रहे हैं user_managementकी तरह 1 स्तर main, अपने scriptsइस शैली का उपयोग करना चाहिए from user_management.Modules import LDAPManagerआयात मॉड्यूल के लिए।

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