कोड रिपॉजिटरी के साथ काम करते समय संसाधनों के सापेक्ष रास्तों का उल्लेख कैसे करें


187

हम एक कोड रिपॉजिटरी के साथ काम कर रहे हैं जो विंडोज और लिनक्स दोनों में तैनात है - कभी-कभी अलग-अलग निर्देशिकाओं में। परियोजना के अंदर मॉड्यूल में से एक को परियोजना में गैर-पायथन संसाधनों में से एक (सीएसवी फाइलें, आदि) का संदर्भ कैसे देना चाहिए?

अगर हम कुछ ऐसा करते हैं:

thefile=open('test.csv')

या:

thefile=open('../somedirectory/test.csv')

यह केवल तभी काम करेगा जब स्क्रिप्ट एक विशिष्ट निर्देशिका से चलायी जाती है, या निर्देशिकाओं का सबसेट।

मैं क्या करना चाहूंगा कुछ इस तरह है:

path=getBasePathOfProject()+'/somedirectory/test.csv'
thefile=open(path)

क्या यह संभव है?

जवाबों:


255

वर्तमान फ़ाइल पथ के सापेक्ष फ़ाइल नाम का उपयोग करने का प्रयास करें। './My_file' के लिए उदाहरण:

fn = os.path.join(os.path.dirname(__file__), 'my_file')

पायथॉन 3.4+ में आप पाथलिब का भी उपयोग कर सकते हैं :

fn = pathlib.Path(__file__).parent / 'my_file'

3
मुझे लगता है कि यह समाधान केवल तभी काम करेगा जब संसाधन अजगर फ़ाइल की एक ही निर्देशिका में है, या इसकी एक उप-निर्देशिका में है। जब आपके पास निम्न ट्री संरचना होती है, तो आप इसे कैसे हल करते हैं: / Project_Root_dir / python_files_dir / यहाँ कुछ और उप-पृष्ठ py_file.py / Resources / कुछ उप-विभाजक यहाँ resource_file.csv
olamundo

1
क्षमा करें, फ़ाइल का पेड़ उस अंतिम संदेश पर आधारित हो गया है ... दूसरा प्रयास करें: आपके पास /Project_Root_dir/python_files_dir/some_subdirs/py_file.py पर आपकी फ़ाइल है और आप /Project_Root_dir
ओलमुंडो

28
ज्वाइन (foo, '..') का उपयोग करके आपको मूल निर्देशिका में लाने में सक्षम होना चाहिए। तो / root / python_files / मॉड्यूल / myfile से, os.path.join (os.path.dirname ( __file__), '..', '..', 'resource') का उपयोग करें
c089

7
os.pardirसे थोड़ा बेहतर है '..', हालांकि दोनों POSIX और विंडोज दोनों पर बराबर हैं।
davidchambers

4
@cedbeu: यह मेरे द्वारा आए हर सिस्टम पर बराबर है और मुझे लगता है कि आज के समय में हर सिस्टम अजगर चलता है (कृपया मुझे सही करें अगर मैं यहां गलत हूं)। हालाँकि, यदि आप भविष्य में एक अलग पथ विभाजक का उपयोग करके सिस्टम में पोर्ट किए जाने की अपेक्षा करते हैं और चाहते हैं कि आपका कोड इसके लिए तैयार हो, तो os.pardir अधिक पोर्टेबल होगा। मैं ऐसा मामला बनाऊंगा कि हर प्रोग्रामर, यहां तक ​​कि जो कभी भी किसी अजगर को नहीं पढ़ता है, वह ".." का अर्थ जानता है, जबकि "os.pardir" अप्रत्यक्ष का एक स्तर है, जिसे दस्तावेज़ में व्यक्तिगत रूप से देखना होगा। ' d "" .. से चिपके रहते हैं।
c089

40

यदि आप सेटअप टूल का उपयोग कर रहे हैं या वितरित (एक सेटअप थ्रू इनस्टॉल) तो इन पैकेज्ड संसाधनों तक पहुँचने का "सही" तरीका पैकेज_स्रोतों का उपयोग करने वाला प्रतीत होता है।

आपके मामले में उदाहरण होगा

import pkg_resources
my_data = pkg_resources.resource_string(__name__, "foo.dat")

बेशक कौन सा संसाधन पढ़ता है और बाइनरी डेटा my_data का मूल्य होगा

यदि आपको केवल फ़ाइल नाम की आवश्यकता है तो आप भी उपयोग कर सकते हैं

resource_filename(package_or_requirement, resource_name)

उदाहरण:

resource_filename("MyPackage","foo.dat")

लाभ यह है कि इसकी गारंटी काम करने के लिए है भले ही यह अंडे की तरह एक संग्रह वितरण हो।

Http://packages.python.org/distribute/pkg_resources.html#resourcemanager-api देखें


3
मुझे पता है कि यह एक पुराना उत्तर है, मेरा पसंदीदा तरीका है (/ था शायद?) Pkg_resources का उपयोग करने के लिए, लेकिन ज़िपित अंडे के गायब होने के साथ, क्या __file__अच्छे पुराने दिनों की तरह ही उपयोग करने में कोई नुकसान है ?
Pykler

1
यह एक ठोस दृष्टिकोण है। यहां तक ​​कि अगर अंडे का सम्मेलन दूर हो रहा है, तो सेटपूल नहीं हैं और कई अभी भी जीआईटी रिपोस के खिलाफ डिप्स स्थापित कर रहे हैं जहां अंडे रनटाइम में बनाया गया है
डीपेलमेंट 13

18

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

निरपेक्ष पथ का उपयोग करना सबसे अच्छा समाधान होना चाहिए:

import os
package_dir = os.path.dirname(os.path.abspath(__file__))
thefile = os.path.join(package_dir,'test.cvs')

15

मैं अक्सर इसके समान कुछ का उपयोग करता हूं:

import os
DATA_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), 'datadir'))

# if you have more paths to set, you might want to shorten this as
here = lambda x: os.path.abspath(os.path.join(os.path.dirname(__file__), x))
DATA_DIR = here('datadir') 

pathjoin = os.path.join
# ...
# later in script
for fn in os.listdir(DATA_DIR):
    f = open(pathjoin(DATA_DIR, fn))
    # ...

चर

__file__

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

  • पथ निरपेक्ष है, लेकिन फिर भी सापेक्ष है
  • परियोजना अभी भी एक रिश्तेदार कंटेनर में तैनात की जा सकती है

लेकिन आपको प्लेटफ़ॉर्म संगतता के लिए देखने की आवश्यकता है - विंडोज 'os.pathsep UNIX से अलग है।


5
import os
cwd = os.getcwd()
path = os.path.join(cwd, "my_file")
f = open(path)

आप अपने cwdउपयोग को सामान्य करने का भी प्रयास करें os.path.abspath(os.getcwd())। अधिक जानकारी यहाँ


3
बहुत कम उपयोग-मामले जहां cwdएक मॉड्यूल का मार्ग है, हालांकि
cedbeu

यह स्क्रिप्ट के द्वारा निर्धारित एक ही डायर (या काम करने वाले डायर) से एक पैकेज के अंदर काम नहीं करता है।
अलेक्जेंड्रा

यह काम नहीं करेगा यदि उपयोगकर्ता विभिन्न निर्देशिका से निरपेक्ष पथ का उपयोग करके कार्यक्रम चलाता है। जैसे python3 /usr/someone/test.py
sgrpwr

2

आप __file__वैरिएबल में बिल्ड का उपयोग कर सकते हैं । इसमें वर्तमान फ़ाइल का पथ शामिल है। मैं आपकी परियोजना की जड़ में एक मॉड्यूल में getBaseOfProject लागू करूंगा। वहाँ मुझे रास्ता मिल जाएगा __file__और वह वापस आ जाएगी। यह विधि तब आपके प्रोजेक्ट में हर जगह उपयोग की जा सकती है।


0

मैं यहाँ थोड़ा रुक गया। कुछ संसाधन फ़ाइलों को एक व्हील फ़ाइल में पैकेज करना और उन्हें एक्सेस करना चाहते थे। क्या पैकेजिंग ने मैनिफ़ेस्ट फ़ाइल का उपयोग किया था, लेकिन जब तक यह एक उप-निर्देशिका नहीं थी, तब तक पाइप इंस्टॉल इसे स्थापित नहीं कर रहा था। इन आकर्षक दृश्यों की उम्मीद करने से मदद मिलेगी

├── cnn_client
   ├── image_preprocessor.py
   ├── __init__.py
   ├── resources
      ├── mscoco_complete_label_map.pbtxt
      ├── retinanet_complete_label_map.pbtxt
      └── retinanet_label_map.py
   ├── tf_client.py

MANIFEST.in

recursive-include cnn_client/resources *

मानक setup.py का उपयोग कर एक weel बनाया गया। पाइप ने पहिया फ़ाइल को स्थापित किया। स्थापना के बाद जाँच की जाती है कि क्या संसाधन स्थापित हैं। वो हैं

ls /usr/local/lib/python2.7/dist-packages/cnn_client/resources

mscoco_complete_label_map.pbtxt
retinanet_complete_label_map.pbtxt 
 retinanet_label_map.py  

इन फ़ाइलों तक पहुँचने के लिए tfclient.py में। से

templates_dir = os.path.join(os.path.dirname(__file__), 'resources')
 file_path = os.path.join(templates_dir, \
            'mscoco_complete_label_map.pbtxt')
        s = open(file_path, 'r').read()

और यह काम करता है।


-5

मैंने इसका उत्तर जानने में लंबा समय बिताया, लेकिन मुझे आखिरकार यह मिल गया (और यह वास्तव में बहुत सरल है):

import sys
import os
sys.path.append(os.getcwd() + '/your/subfolder/of/choice')

# now import whatever other modules you want, both the standard ones,
# as the ones supplied in your subfolders

यह अजगर के लिए निर्देशिका के लिए अपने सबफ़ोल्डर के सापेक्ष पथ को जोड़ देगा यह देखने में बहुत तेज़ और गंदा है, लेकिन यह एक आकर्षण की तरह काम करता है :)


6
यह तभी काम करेगा जब आप पायथ प्रोग्राम को उसी निर्देशिका से चला रहे हों, जो प्रश्न में .py फ़ाइल के रूप में हो। और उस मामले में, आप open('your/subfolder/of/choice')वैसे भी कर सकते हैं ।
पॉल फिशर

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