python - विभिन्न फ़ोल्डर से फ़ाइलें आयात करना


मेरे पास निम्न फ़ोल्डर संरचना है

application/app/folder/file.py

और मैं कुछ फाइलों में file.py से एक और पायथन फ़ाइल आयात करना चाहता हूं जो कि में रहता है

application/app2/some_folder/some_file.py

मैंने कोशिश की

from application.app.folder.file import func_name

और कुछ अन्य विभिन्न प्रयासों पर अभी तक मैं ठीक से आयात करने का प्रबंधन नहीं कर सका। मैं यह कैसे कर सकता हूँ?




Answers


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

हालांकि, आप रनटाइम पर पायथन पथ में जोड़ सकते हैं:

# some_file.py
import sys
sys.path.insert(0, '/path/to/application/app/folder')

import file



इसमें कुछ भी गलत नहीं है:

from application.app.folder.file import func_name

सुनिश्चित करें कि फ़ोल्डर में एक __init__.py भी शामिल है, यह पैकेज के रूप में शामिल करने की अनुमति देता है। निश्चित नहीं है कि पीठोंपथ के बारे में अन्य जवाब क्यों बताते हैं




जब मॉड्यूल समानांतर स्थानों में होते हैं, तो प्रश्न के रूप में:

application/app2/some_folder/some_file.py
application/app2/another_folder/another_file.py

यह लयबद्धता एक मॉड्यूल दूसरे को दिखाई देता है:

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



चूंकि आपका सवाल * निकस विशिष्ट लगता है, मुझे लगता है कि पर्यावरण चर का उपयोग करने के लिए एक साफ रास्ता होगा

PYTHONPATH

जैसा कि दस्तावेज में वर्णित है: पायथन 2 , पायथन 3

export PYTHONPATH=$HOME/dirWithScripts/:$PYTHONPATH



जो मैं जानता हूं, उस फ़ंक्शन के फ़ोल्डर में सीधे एक __init__.py फ़ाइल जोड़ें, जिसे आप आयात करना चाहते हैं, वह काम करेगा।




लिनक्स पर अजगर 3 में मेरे लिए काम किया

import sys  
sys.path.append(pathToFolderContainingScripts)  
from scriptName import functionName #scriptName without .py extension  



अपने अजगर प्रोजेक्ट के लिए रूट डायरेक्टरी के रूप में application को ध्यान में रखते हुए, application , app और folder फ़ोल्डर्स में खाली __init__.py फ़ाइल बनाएं। फिर some_file.py की परिभाषा प्राप्त करने के लिए अपने some_file.py बदलाव करें:

import sys
sys.path.insert(0, r'/from/root/directory/application')

from application.app.folder.file import func_name ## You can also use '*' wildcard to import all the functions in file.py file.
func_name()



यह मेरे लिए खिड़कियों पर काम करता है

# some_file.py on mainApp/app2 
import sys
sys.path.insert(0, sys.path[0]+'\\app2')

import some_file



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

मैंने इसे लिनक्स पर परीक्षण किया है लेकिन किसी भी आधुनिक ओएस में काम करना चाहिए जो प्रतीकात्मक लिंक का समर्थन करता है।

इस दृष्टिकोण के लिए एक फायदा यह है कि आप अपने खुद के स्थानीय एसवीसी शाखा काम की प्रतिलिपि में बैठे मॉड्यूल को इंगित कर सकते हैं जो कि विकास चक्र के समय को सरलता से सरल कर सकता है और मॉड्यूल के विभिन्न संस्करणों को प्रबंधित करने की असफलताओं को कम कर सकता है।




आपकी समस्या यह है कि पायथन इस फ़ाइल के लिए पायथन निर्देशिका में देख रहा है और इसे नहीं खोज रहा है। आपको यह निर्दिष्ट करना होगा कि आप उस डायरेक्टरी के बारे में बात कर रहे हैं जो आप में हैं और पायथन एक नहीं हैं।

ऐसा करने के लिए आप इसे बदल सकते हैं:

from application.app.folder.file import func_name

इसके लिए:

from .application.app.folder.file import func_name

डॉट को जोड़कर आप कह रहे हैं कि इस फ़ोल्डर को अजगर निर्देशिका में देखने के बजाय एप्लिकेशन फ़ोल्डर के लिए देखो।

(उम्मीद है कि यह आपकी समस्या को हल करता है!)




मैं काफी विशेष हूँ: मैं विंडोज के साथ अजगर का उपयोग करता हूँ!

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

और जब विंडोज़ का उपयोग करते हुए दोनों \ और / को फ़ाइल के नाम के लिए विभाजक के रूप में इस्तेमाल किया जा सकता है और निश्चित तौर पर आपको पायथन तारों में \
कुछ वैध उदाहरण:

sys.path.append('c:\\tools\\mydir')
sys.path.append('..\\mytools')
sys.path.append('c:/tools/mydir')
sys.path.append('../mytools')

(ध्यान दें: मुझे लगता है कि / उस घटना से अधिक सुविधाजनक है, अगर यह कम 'विंडोज-नेटिव्ह' है क्योंकि यह लिनक्स-संगत और आसान है और लिखने और विंडोज एक्सप्लोरर को कॉपी करता है)




अन्य परिवेशों में आवेदन को स्थानांतरित करते समय एक निरपेक्ष पथ के साथ sys.path.append का उपयोग आदर्श नहीं है। सापेक्ष पथ का उपयोग करना हमेशा काम नहीं करेगा क्योंकि वर्तमान कार्य निर्देशिका स्क्रिप्ट पर निर्भर करता है।

चूंकि ऐप्लिकेशन फ़ोल्डर संरचना तय हो गई है, इसलिए हम पूर्ण पथ प्राप्त करने के लिए ओएस। उदाहरण के लिए, यदि यह संरचना है:

/home/me/application/app2/some_folder/vanilla.py
/home/me/application/app2/another_folder/mango.py

और मान लें कि आप "आम" मॉड्यूल आयात करना चाहते हैं। आप vanilla.py में निम्नलिखित कर सकते हैं:

import sys, os.path
mango_dir = (os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
+ '/another_folder/')
sys.path.append(mango_dir)
import mango

बेशक, आप mango_dir चर की आवश्यकता नहीं है।

समझने के लिए कि यह इंटरैक्टिव सत्र उदाहरण कैसे दिखता है:

>>> import os
>>> mydir = '/home/me/application/app2/some_folder'
>>> newdir = os.path.abspath(os.path.join(mydir, '..'))
>>> newdir
    '/home/me/application/app2'
>>> newdir = os.path.abspath(os.path.join(mydir, '..')) + '/another_folder'
>>> 
>>> newdir
'/home/me/application/app2/another_folder'
>>> 

और os.path प्रलेखन की जांच करें




आप पायथन शेल को F5 दबाकर ताज़ा कर सकते हैं, या रन-> रन मॉड्यूल पर जा सकते हैं। इस तरह आपको फ़ाइल से कुछ पढ़ने के लिए निर्देशिका को बदलना नहीं पड़ता है। अजगर स्वचालित रूप से डायरेक्टरी बदल देगा। लेकिन अगर आप पायथन शैल में अलग-अलग निर्देशिका से अलग फाइलों के साथ काम करना चाहते हैं, तो आप sys में निर्देशिका बदल सकते हैं, जैसा कि कैमरन ने पहले कहा था।




sys.path.insert(0, '/path/to/application/app/folder')