2011-03-04 19 views
12

उपप्रक्रिया मॉड्यूल सुविधा समारोह call है, जो 2.6 और 3.1 दोनों में इस तरह कार्यान्वित किया जाता है है:पाइथन का subprocess.call इस तरह कार्यान्वित क्यों किया जाता है?

def call(*popenargs, **kwargs): 
    return Popen(*popenargs, **kwargs).wait() 

इस कार्य के लिए प्रलेखन एक लाल चेतावनी वहन करती है, पढ़ने:

चेतावनी : Popen.wait() की तरह, यह stdout=PIPE और/या stderr=PIPE का उपयोग करते समय डेडलॉक होगा और बाल प्रक्रिया पर्याप्त पाइप को पाइप में उत्पन्न करती है जैसे कि यह ओएस पाइप बफर के लिए अधिक डेटा स्वीकार करने के लिए प्रतीक्षा कर रहा है।

Popen.wait() प्रलेखन ऐसे हालात में बजाय Popen.communicate() उपयोग करने के लिए कहते हैं। खैर, तो call क्यों नहीं है, बस इसके बजाय नीचे लागू किया गया है, इसलिए बेवकूफ चेतावनी को हटाया जा सकता है, और इस तरह की मूर्ख सीमाएं मानक पुस्तकालय से हटा दी गई हैं?

def call(*args, **kwargs): 
    input = kwargs.pop("input", None) 
    p = Popen(*args, **kwargs) 
    p.communicate(input) 
    return p.returncode 

मुझे यकीन है कि एक कारण है। मैं क्या खो रहा हूँ?

उत्तर

8

मैं कुछ समय बिताया PEP-324, जो उपप्रक्रिया मॉड्यूल शुरू के माध्यम से देख, यह पता लगाने की कोशिश कर रहा है डिजाइन फैसले शामिल है, लेकिन मुझे लगता है कि इस सवाल का जवाब वास्तव में बहुत सरल है:

वहाँ है कोई कारण नहींstdout=PIPE पारित करने के लिए या stderr=PIPE से subprocess.call, इसलिए तथ्य यह है कि यह डेडलॉक अप्रासंगिक है।

एकमात्र कारण पारित करने के लिए stdout=PIPE या stderr=PIPEsubprocess.Popen ताकि आप फ़ाइल वस्तुओं के रूप में popen उदाहरण के stdout और stderr विशेषताओं का उपयोग कर सकते हैं। चूंकि subprocess.call आपको पॉपन इंस्टेंस देखने की अनुमति नहीं देता है, इसलिए पीआईपीई विकल्प अप्रासंगिक हो जाते हैं।

Popen.communicate (पाइप की निगरानी करके डेडलॉक से बचने के लिए अतिरिक्त धागे बनाने) के संभावित ओवरहेड हैं, और इस मामले में कोई लाभ नहीं है, इसलिए इसका उपयोग करने का कोई कारण नहीं है।

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

# option 1 
with open(os.devnull, 'w') as dev_null: 
    subprocess.call(['command'], stdout=dev_null, stderr=dev_null) 

# option 2 
subprocess.call(['command >& /dev/null'], shell=True) 

पाइप फ़ाइलों को करने का इरादा कभी नहीं करने के लिए उत्पादन के सभी पर कब्जा करने के उपयोग।

+0

प्रोग्राम के आउटपुट को नियंत्रित करना stdout = PIPE और stderr = PIPE का उपयोग करने के लिए एक रेजोन है। यही है, पाइथन 'कमांड>/dev/null 2> और 1' के बराबर है और फिर बैश में '$?' की जांच कर रहा है। –

+0

क्या यह बेहतर नहीं होगा 'stdout = open ('/dev/null ',' w '), stderr = STDOUT'? –

+0

@ बाफ मुझे लगता है, लेकिन बिंदु यह था कि वहाँ _is_ stdout = और stderr = कीवर्ड कॉल 'कॉल' का उपयोग करने का एक कारण है। –

2

यदि आप जो करना चाहते हैं वह एक आदेश चलाएं और यह निर्धारित करने के लिए निकास स्थिति प्राप्त करें कि यह सफल हुआ या विफल हुआ तो आपको पाइप के माध्यम से इसके साथ संवाद करने की आवश्यकता नहीं है। यह subprocess.call() विधि की सुविधा है। सबप्रोसेस मॉड्यूल में अन्य सुविधा फ़ंक्शन भी हैं जो पॉपपे ऑब्जेक्ट्स को कुशल तरीके से उपयोग करने के कई सामान्य उपयोगों को समाहित करते हैं।

यदि आपको कॉल प्रक्रियाओं का उपयोग न करने के बजाय कहीं भी बच्चे प्रक्रियाओं को stdout या stderr को पाइप करने की आवश्यकता है, तो एक पॉपन ऑब्जेक्ट का उपयोग करें और इसके साथ संवाद करें() जैसे दस्तावेज़ दस्तावेज़।

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