2009-09-16 17 views
104

के लिए निर्देशिका स्क्रिप्ट काम कर रही बदले मैं crontab से हर मिनट एक अजगर खोल चलाएँ:अजगर: स्क्रिप्ट के अपने निर्देशिका

* * * * * /home/udi/foo/bar.py 

/home/udi/foo कुछ आवश्यक उपनिर्देशिका, /home/udi/foo/log और /home/udi/foo/config की तरह है, जो /home/udi/foo/bar.py को संदर्भित करता है।

समस्या यह है कि crontab एक अलग कार्य निर्देशिका से स्क्रिप्ट चलाता है, इसलिए ./log/bar.log खोलने का प्रयास विफल हो जाता है।

क्या स्क्रिप्ट को अपनी निर्देशिका में कार्य निर्देशिका को बदलने के लिए स्क्रिप्ट को बताने का कोई अच्छा तरीका है? मैं एक ऐसा समाधान चाहता हूं जो स्क्रिप्ट को स्पष्ट रूप से कहने के बजाय किसी भी स्क्रिप्ट स्थान के लिए काम करेगा।

संपादित करें:

os.chdir(os.path.dirname(sys.argv[0])) 

सबसे कॉम्पैक्ट सुरुचिपूर्ण समाधान कर दिया गया। आपके उत्तरों और स्पष्टीकरण के लिए धन्यवाद!

+0

'crontab' उपयोग-मामले से संबंधित नहीं है:' sys.argv [0] 'और' __file__' दोनों 'execfile() 'का उपयोग करके स्क्रिप्ट चलाए जाने पर असफल हो जाते हैं; ['निरीक्षण 'आधारित समाधान] (http://stackoverflow.com/a/22881871/4279) इसके बजाय इस्तेमाल किया जा सकता है। – jfs

उत्तर

129

यह आपके वर्तमान कार्यशील निर्देशिका बदल जाएगा ताकि संबंधित पथ को खोलने के लिए काम करेंगे:

import os 
os.chdir("/home/udi/foo") 

हालांकि, आप निर्देशिका अपने अजगर स्क्रिप्ट स्थित है में परिवर्तित करने का तरीका पूछा, भले ही आप नहीं जानते जब आप अपनी स्क्रिप्ट लिख रहे हों तो कौन सी निर्देशिका होगी। ऐसा करने के लिए, आप os.path कार्यों का उपयोग कर सकते हैं:

import os 

abspath = os.path.abspath(__file__) 
dname = os.path.dirname(abspath) 
os.chdir(dname) 

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

+1

निर्देशिका हार्डकोडिंग के बराबर है। – Ikke

+0

मैंने स्क्रिप्ट की निर्देशिका में बदलने के तरीके के बारे में जानकारी जोड़ा; मैंने एक आंशिक जवाब पोस्ट किया, जबकि मैंने os.path फ़ंक्शंस को देखा, जिसे मैं अपने सिर के ऊपर से याद नहीं कर सका। –

+2

यदि आप इसे सिम्लिंक से चला रहे हैं, तो यह काम नहीं करेगा। 'Sys.argv [0]' के बजाय '__file__' का प्रयोग करें। –

15

ऐसा मत करें।

आपकी स्क्रिप्ट और आपके डेटा को एक बड़ी निर्देशिका में मैश नहीं किया जाना चाहिए। अपने डेटा से अलग कुछ ज्ञात स्थान (site-packages या /var/opt/udi या कुछ) में अपना कोड रखें। यह सुनिश्चित करने के लिए कि आपके पास वर्तमान और पिछले संस्करण एक दूसरे से अलग हैं, अपने कोड पर अच्छे संस्करण नियंत्रण का उपयोग करें ताकि आप पिछले संस्करणों पर वापस आ सकें और भविष्य के संस्करणों का परीक्षण कर सकें।

नीचे पंक्ति: कोड और डेटा को मिटाना न करें।

डेटा कीमती है। कोड आता है और चला जाता है।

कार्य निर्देशिका को कमांड-लाइन तर्क मान के रूप में प्रदान करें। आप एक पर्यावरण चर के रूप में एक डिफ़ॉल्ट प्रदान कर सकते हैं। इसे घटाएं (या अनुमान लगाएं)

इसे एक आवश्यक तर्क मान बनाएं और ऐसा करें।

import sys 
import os 
working= os.environ.get("WORKING_DIRECTORY","/some/default") 
if len(sys.argv) > 1: working = sys.argv[1] 
os.chdir(working) 

अपने सॉफ़्टवेयर के स्थान के आधार पर निर्देशिका "मान लें" न करें। यह लंबे समय तक अच्छी तरह से काम नहीं करेगा।

+8

मुझे लगता है कि आप बड़े सॉफ़्टवेयर पैकेजों के लिए कोड और डेटा को अलग करने के बारे में सही हैं, लेकिन ऐसा लगता है कि यह एक छोटी रखरखाव स्क्रिप्ट के लिए काफी दूर है । मैं संस्करण नियंत्रण के बारे में पूरी तरह से सहमत हूं। –

+2

एस लॉट सही है। हमेशा डेटा और कोड अलग रखें, जब तक कि डेटा क्षणिक न हो। उदाहरण के लिए, यदि आपके पास आइकन हैं, तो यह डेटा है, लेकिन यह क्षणिक नहीं है, और यह सॉफ़्टवेयर बंडल के सापेक्ष विचार करने के लिए समझ में आता है (जो भी इसका मतलब है) –

+4

@Udi Pasmon: बिल्कुल दूर नहीं। यह "छोटी रखरखाव स्क्रिप्ट" है जो संगठनों को गहरी परेशानी में डालती है। अब से साल, यह "छोटी रखरखाव स्क्रिप्ट" और इसके बच्चे और व्युत्पन्न और डेटा फाइलें विघटन और पुनर्मूल्यांकन के लिए एक दुःस्वप्न होगी। जितना संभव हो सके कोड से डेटा रखें - सबकुछ के लिए पैरामीटर पास करें - कुछ भी नहीं मानें। –

26

sys.path[0] का उपयोग करके आप एक छोटा संस्करण प्राप्त कर सकते हैं।

os.chdir(sys.path[0]) 

http://docs.python.org/library/sys.html#sys.path

से कार्यक्रम स्टार्टअप पर प्रारंभ के रूप में, इस सूची के पहले आइटम, path[0], स्क्रिप्ट करने के लिए इस्तेमाल किया गया था पायथन दुभाषिया आह्वान युक्त निर्देशिका है

11

अपने crontab कमांड को

पर बदलें

(...) एक उप-खोल शुरू करता है जो आपके क्रॉन्ड को एक कमांड के रूप में निष्पादित करता है। || exit 1 निर्देशिका के अनुपलब्ध होने पर आपके cronjob को विफल करने का कारण बनता है।

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

+0

यह एक बेहद अच्छा समाधान है। मैं आम तौर पर '|| जैसी चीजों को जोड़ने के लिए अन्य लोगों के उत्तरों को संपादित करता हूं बाहर निकलें 1'। यह देखने के लिए ताज़ा है। हालांकि मुझे आश्चर्य है कि आप केवल 'सीडी/होम/udi/foo/&&।/Bar.py' –

+2

@ ब्रुनोब्रोनोस्की को स्पष्ट' निकास 1 'के साथ क्यों नहीं करेंगे, आपके क्रॉन्ड को त्रुटि की अधिसूचना दी जाएगी, और अधिकांश मामलों में विफलता की एक ईमेल अधिसूचना भेजी जाएगी। –

संबंधित मुद्दे