2010-04-07 14 views
7

मैं पर्ल में कुछ खोल कमांड पाइप करने के बराबर एक पायथन का उपयोग करना चाहता था। खुले के पायथन संस्करण की तरह कुछ (पीआईपीई, "कमांड |")।पायथन का पॉपन क्लीनअप

मैं उपप्रक्रिया मॉड्यूल के लिए जाने के लिए और इस प्रयास करें:

p = subprocess.Popen("zgrep thingiwant largefile", shell=True, stdout=subprocess.PIPE) 

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

grep: writing output: Broken pipe 

कुछ मिलियन बार stderr से अधिक spewed मिलता है। मुझे लगता है कि मैंने अच्छी तरह से आशा की थी कि यह सब मेरे लिए ख्याल रखा जाएगा, लेकिन यह सच नहीं है। पी को कॉल करना या पीना मारना मदद नहीं करता है। प्रक्रिया तालिका को देखो, मैं देखता हूं कि यह/bin/sh प्रक्रिया को मारता है, लेकिन टूटने वाली पाइप के बारे में शिकायत करने के लिए बच्चे को gzip छोड़ देता है।

ऐसा करने का सही तरीका क्या है?

+1

क्या आप अपने उपप्रोसेसर 'पी' समाप्त होने से पहले दुभाषिया से बाहर निकल रहे हैं? – physicsmichael

उत्तर

9

मुद्दा यह है कि pipe भरा हुआ है। उपप्रोसेस बंद हो जाता है, पाइप को खाली करने की प्रतीक्षा करता है, लेकिन फिर आपकी प्रक्रिया (पायथन दुभाषिया) छोड़ती है, पाइप के अंत को तोड़ती है (इसलिए त्रुटि संदेश)।

p.wait() आप मदद नहीं करेगा:

चेतावनी यह अगर बच्चे प्रक्रिया ऐसी है कि वह ओएस पाइप बफर के लिए इंतज़ार कर ब्लॉक अधिक डेटा स्वीकार करने के लिए एक stdout या stderr पाइप के लिए पर्याप्त उत्पादन उत्पन्न गतिरोध होगा। इससे बचने के लिए communicate() का उपयोग करें।

http://docs.python.org/library/subprocess.html#subprocess.Popen.wait

p.communicate() मदद मिलेगी नहीं:

नोट डेटा को पढ़ने स्मृति में बफ़र है, इसलिए यदि डेटा आकार बड़ा या असीमित है इस विधि का उपयोग नहीं करते।

http://docs.python.org/library/subprocess.html#subprocess.Popen.communicate

p.stdout.read(num_bytes) आप मदद नहीं करेगा: भरने अन्य ओएस पाइप बफ़र्स में से किसी की वजह से

चेतावनी उपयोग communicate() बजाय .stdin.write, .stdout.read या .stderr.read गतिरोध से बचने के लिए और बाल प्रक्रिया को अवरुद्ध करना

http://docs.python.org/library/subprocess.html#subprocess.Popen.stdout

कहानी का नैतिक है, बड़े उत्पादन के लिए, subprocess.PIPE आप कुछ विफलता के लिए बर्बाद है, जब आपके प्रोग्राम डेटा को पढ़ने के लिए कोशिश कर रहा है (मुझे लगता है कि आप डाल करने के लिए सक्षम होना चाहिए p.stdout.read(bytes)while p.returncode is None: लूप में, लेकिन उपरोक्त चेतावनी से पता चलता है कि यह डेडलॉक हो सकता है)।

डॉक्स इस के साथ एक खोल पाइप की जगह सलाह देते हैं:

p1 = Popen(["zgrep", "thingiwant", "largefile"], stdout=PIPE) 
p2 = Popen(["processreceivingdata"], stdin=p1.stdout, stdout=PIPE) 
output = p2.communicate()[0] 

सूचना है कि p2p1 से सीधे अपने मानक इनपुट ले जा रहा है। यह डेडलॉक्स से बचने चाहिए, लेकिन उपरोक्त विरोधाभासी चेतावनियां, जो जानता है।

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

0

आपने इस प्रक्रिया को कैसे निष्पादित किया?

उचित तरीके से उपयोग करने

p.communicate() 

अधिक जानकारी के लिए डॉक्स देखें है।

+0

यह तब भी होता है जब मैं प्रक्रिया के साथ कभी संवाद नहीं करता। ऑब्जेक्ट पी बनाना और फिर दुभाषिया से बाहर निकलना इस समस्या का कारण बनता है। –

+0

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

2

के बाद आप पाइप खोलते हैं, तो आप आदेश उत्पादन के साथ काम कर सकते हैं: p.stdout:

for line in p.stdout: 
    # do stuff 
p.stdout.close() 
0

आप समाप्त करने के लिए प्रक्रिया के लिए wait की जरूरत है:

import subprocess 
p = subprocess.Popen("cat /mach_kernel", shell=True) 
p.wait() 

वैकल्पिक रूप से, आप कैप्चर कर सकते हैं कार्यक्रम के मानक आउटपुट (यदि आपके पास के रूप में), और शायद अपने मानक त्रुटि, और फिर फोन communicate:

import subprocess 
p = subprocess.Popen("cat /mach_kernel", shell=True, 
        stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
stdout, stderr = p.communicate() 
संबंधित मुद्दे