subprocess
कोई आदेश नहीं मिलने पर OSError
अपवाद उठाएगा।
जब आदेश मिलता है, और subprocess
आपके लिए आदेश चलाता है, तो परिणाम कोड आदेश से वापस कर दिया जाता है। मानक यह है कि कोड 0 का अर्थ सफलता है, और कोई विफलता कुछ गैर-शून्य त्रुटि कोड है (जो भिन्न होती है; आपके द्वारा चलाए जा रहे विशिष्ट आदेश के लिए दस्तावेज़ देखें)।
तो, यदि आप OSError
पकड़ते हैं तो आप गैर-मौजूद कमांड को संभाल सकते हैं, और यदि आप परिणाम कोड जांच सकते हैं तो आप यह पता लगा सकते हैं कि आदेश सफल हुआ या नहीं।
बड़ी बात के बारे में subprocess
है कि आप इसे stdout
और stderr
से सभी पाठ इकट्ठा कर सकते हैं, और आप तो इसे त्यागने कर सकते हैं या इसे वापस या यह प्रवेश करें या इसे प्रदर्शित के रूप में आप की तरह है। मैं अक्सर एक रैपर का उपयोग करता हूं जो कमांड से सभी आउटपुट को त्याग देता है, जब तक कि आदेश stderr
से पाठ आउटपुट में विफल रहता है।
मैं मानता हूं कि आपको उपयोगकर्ताओं को निष्पादन योग्य प्रतिलिपि बनाने के लिए नहीं कहना चाहिए। कार्यक्रम PATH
चर में सूचीबद्ध निर्देशिका में होना चाहिए; यदि कोई प्रोग्राम गुम है, तो इसे स्थापित किया जाना चाहिए, या यदि यह PATH
पर निर्देशिका में स्थापित नहीं है, तो उपयोगकर्ता को उस निर्देशिका को शामिल करने के लिए PATH
अद्यतन करना चाहिए।
ध्यान दें कि आप निष्पादनयोग्य के लिए विभिन्न हार्ड-कोडेड पथ के साथ subprocess
कई बार प्रयास करने का विकल्प है:
import os
import subprocess as sp
def _run_cmd(s_cmd, tup_args):
lst_cmd = [s_cmd]
lst_cmd.extend(tup_args)
result = sp.call(lst_cmd)
return result
def run_lumberjack(*tup_args):
try:
# try to run from /usr/local/bin
return _run_cmd("/usr/local/bin/lumberjack", tup_args)
except OSError:
pass
try:
# try to run from /opt/forest/bin
return _run_cmd("/opt/forest/bin/lumberjack", tup_args)
except OSError:
pass
try:
# try to run from "bin" directory in user's home directory
home = os.getenv("HOME", ".")
s_cmd = home + "/bin/lumberjack"
return _run_cmd(s_cmd, tup_args)
except OSError:
pass
# Python 3.x syntax for raising an exception
# for Python 2.x, use: raise OSError, "could not find lumberjack in the standard places"
raise OSError("could not find lumberjack in the standard places")
run_lumberjack("-j")
संपादित करें: इसके बारे में एक छोटा सा सोच के बाद, मैं पूरी तरह से ऊपर फिर से लिखने का फैसला किया। बस स्थानों की एक सूची पास करने के लिए यह बहुत साफ है, और जब तक कोई काम नहीं करता तब तक लूप वैकल्पिक स्थानों को आज़माएं। लेकिन अगर उपयोगकर्ता की जरूरत नहीं थी, तो मैं उपयोगकर्ता की होम निर्देशिका के लिए स्ट्रिंग बनाना नहीं चाहता था, इसलिए मैंने विकल्पों की सूची में कॉल करने योग्य बना दिया। यदि इसके बारे में आपके कोई प्रश्न हैं, तो बस पूछें।
import os
import subprocess as sp
def try_alternatives(cmd, locations, args):
"""
Try to run a command that might be in any one of multiple locations.
Takes a single string argument for the command to run, a sequence
of locations, and a sequence of arguments to the command. Tries
to run the command in each location, in order, until the command
is found (does not raise OSError on the attempt).
"""
# build a list to pass to subprocess
lst_cmd = [None] # dummy arg to reserve position 0 in the list
lst_cmd.extend(args) # arguments come after position 0
for path in locations:
# It's legal to put a callable in the list of locations.
# When this happens, we should call it and use its return
# value for the path. It should always return a string.
if callable(path):
path = path()
# put full pathname of cmd into position 0 of list
lst_cmd[0] = os.path.join(path, cmd)
try:
return sp.call(lst_cmd)
except OSError:
pass
raise OSError('command "{}" not found in locations list'.format(cmd))
def _home_bin():
home = os.getenv("HOME", ".")
return os.path.join(home, "bin")
def run_lumberjack(*args):
locations = [
"/usr/local/bin",
"/opt/forest/bin",
_home_bin, # specify callable that returns user's home directory
]
return try_alternatives("lumberjack", locations, args)
run_lumberjack("-j")
'check_call()' अगर कोई आदेश साफ से बाहर नहीं निकलता है (जो मौजूदा अस्तित्वों की अपेक्षा की जाती है) – inspectorG4dget
भी, मैं उपयोगकर्ता को निष्पादन योग्य प्रतिलिपि बनाने के लिए कहने की सलाह नहीं दूंगा, अंतिम उपाय के अलावा । पैकेज मैनेजर सामान स्थापित करने के लिए लगभग हमेशा सबसे अच्छा विकल्प हैं। –
@ डेवब्रंकर: आप 'कॉल' बनाम 'चेक_call' के बारे में थोड़ा उलझन में लगते हैं। 'कॉल' पहले से ही आपको रिटर्न कोड देता है-एक विशेषता के रूप में नहीं, जैसे फ़ंक्शन का रिटर्न वैल्यू। 'Check_call' का उपयोग करने का कारण यह है कि यह आपके लिए उस वापसी कोड की जांच करने का ख्याल रखता है, जिसे 'कॉलडप्रोसेसर' उठाया जाता है। कार्यक्रम के लिए कोई भी आपको 'ओएसआरआरआर' (या इसी तरह, आपके पायथन संस्करण के आधार पर) उठाता है। – abarnert