2012-09-04 9 views
26

Possible Duplicate:
Wrap subprocess' stdout/stderrक्या आप सामान्य रूप से एक अजगर सबप्रोसेस आउटपुट स्टडआउट और स्टेडर बना सकते हैं, लेकिन आउटपुट को स्ट्रिंग के रूप में भी कैप्चर कर सकते हैं?

this question में, hanan-n से पूछा कि क्या यह एक अजगर उपप्रक्रिया कि stdout में आउटपुट करते हुए भी बाद में प्रसंस्करण के लिए एक स्ट्रिंग में उत्पादन रखने के लिए संभव था। ,

output = [] 
p = subprocess.Popen(["the", "command"], stdout=subprocess.PIPE) 
for line in iter(p.stdout.readline, ''): 
    print(line) 
    output.append(line) 

हालांकि, इस समाधान इस मामले में जहां आप दोनों stdout और stderr के लिए ऐसा करना चाहते हैं के लिए सामान्य नहीं है, जबकि संतोषजनक: इस मामले में समाधान हर उत्पादन लाइन पर पाश के लिए गया था और उन्हें मैन्युअल रूप से प्रिंट निम्नलिखित:

  • stdout/stderr से उत्पादन माता पिता प्रक्रिया के पास जाना चाहिए 'stdout/stderr क्रमशः
  • उत्पादन जितना संभव हो उतना वास्तविक समय में किया जाना चाहिए (लेकिन मैं केवल पर तार के लिए उपयोग की जरूरत है अंत)
  • ओ stdout और stderr लाइनों के बीच rder बदला नहीं जाना चाहिए (मुझे पूरा यकीन नहीं है कि यह कैसे काम करेगा अगर subprocess अलग अंतराल पर अपने stdout और stderr कैश flushes; चलो अब है कि हम अच्छा हिस्सा है कि पूरा पंक्तियाँ हो में सब कुछ प्राप्त करने के लिए मान लें?)

मैं subprocess documentation के माध्यम से देखा, लेकिन कुछ भी है कि इस लक्ष्य को हासिल कर सकते हैं नहीं मिल सका। सबसे नज़दीक मुझे मिल सकता है stderr=subprocess.stdout जोड़ना और उपरोक्त के समान समाधान का उपयोग करना है, लेकिन फिर हम नियमित आउटपुट और त्रुटियों के बीच भेद खो देते हैं। कोई विचार? मैं समाधान का अनुमान लगा रहा हूं - यदि कोई है - इसमें p.stdout और p.stderr पर एसिंक्रोनस पढ़ने को शामिल किया जाएगा।

p = subprocess.Popen(["the", "command"]) 
p.wait() # while p runs, the command's stdout and stderr should behave as usual 
p_stdout = p.stdout.read() # unfortunately, this will return '' unless you use subprocess.PIPE 
p_stderr = p.stderr.read() # ditto 
[do something with p_stdout and p_stderr] 
+0

मुझे नहीं लगता कि यह तकनीक (किसी भी आईओ फ़ंक्शन और स्ट्रीम ऑब्जेक्ट्स को लपेटना) सामान्यीकृत नहीं है? – ninjagecko

+0

आप कैसे सुझाव देते हैं कि मैं वास्तविक समय में stdout और stderr पर प्रिंट करने के लिए उपप्रोसेस प्राप्त करता हूं, फिर भी अंत में एक स्ट्रिंग में आउटपुट प्राप्त करते समय, फिर? – pflaquerre

उत्तर

37

यह उदाहरण मेरे लिए काम करने लगता है यह नहीं पता कि आपके पास पढ़ने के लिए कौन सी चीजें होंगी, आपको चुनिंदा या कुछ समकक्ष (एक ट्विस्ट रिएक्टर की तरह) का उपयोग करना चाहिए।

+1

ऑर्डर * सटीक * जैसा नहीं हो सकता है क्योंकि 'stdout' और 'stderr' के बाद मूल दोनों के पास डेटा चुनने के समय डेटा हो सकता है, लेकिन यह एक समाधान के करीब है जैसा मैंने देखा है दूर। धन्यवाद! – pflaquerre

+0

आदेश के बारे में आपका क्या मतलब है? उदाहरण में मैं देता हूं, यदि दोनों से पढ़ने के लिए डेटा है, तो यह पहले stdout को संभालेगा क्योंकि इसकी एफडी सामान्य रूप से stderr की तुलना में कम होगी, और इसे क्रम में वापस करना चाहिए। यदि यह मामला नहीं है या गारंटी नहीं है, तो आप कुछ ऐसा करने के लिए कोड को आसानी से बदल सकते हैं जैसे p.stdout.fileno() ret [0] में: और फिर stderr के लिए वही, जो ऑर्डर की गारंटी देनी चाहिए। –

+0

मैं उस आदेश के बारे में बात कर रहा हूं जिसमें धाराएं लिखी गई थीं। उदाहरण के लिए, उपप्रोसेसर पहले stderr को लिख सकता है, फिर stdout पर कुछ और लिखें, लेकिन 'चयन' अभी भी stderr से पहले stdout से पढ़ा जाएगा, जो वास्तव में वही क्रम नहीं है जैसा वास्तव में हुआ था। सबसे बुरे मामले में, उपप्रोसेस इतना लिखने के लिए लिख रहा है कि प्रक्रिया में चलने तक stderr में कुछ भी बंद हो जाएगा। (जब तक मुझे गलत समझ नहीं आता कि कैसे काम करता है?) – pflaquerre

2

के रूप में ऊपर दो पाठकों, stdout एक stderr के लिए के लिए एक बना सकते हैं और एक नया सूत्र में प्रत्येक शुरू:

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

# -*- Mode: Python -*- 
# vi:si:et:sw=4:sts=4:ts=4 

import subprocess 
import sys 
import select 

p = subprocess.Popen(["find", "/proc"], 
    stdout=subprocess.PIPE, stderr=subprocess.PIPE) 

stdout = [] 
stderr = [] 

while True: 
    reads = [p.stdout.fileno(), p.stderr.fileno()] 
    ret = select.select(reads, [], []) 

    for fd in ret[0]: 
     if fd == p.stdout.fileno(): 
      read = p.stdout.readline() 
      sys.stdout.write('stdout: ' + read) 
      stdout.append(read) 
     if fd == p.stderr.fileno(): 
      read = p.stderr.readline() 
      sys.stderr.write('stderr: ' + read) 
      stderr.append(read) 

    if p.poll() != None: 
     break 

print 'program ended' 

print 'stdout:', "".join(stdout) 
print 'stderr:', "".join(stderr) 

सामान्य तौर पर, किसी भी स्थिति है जहाँ आप एक ही समय में एक से अधिक फ़ाइल वर्णनकर्ता के साथ काम करना चाहते हैं और आप डॉन:

यानी,

p = subprocess.Popen(["the", "command"]) 
t1 = thread.start_new_thread(func,stdout) # create a function with the readers 
t2 = thread.start_new_thread(func,stderr) 
p.wait() 
# your logic here 
+0

धागे को क्रमबद्ध करने के लिए समय का उपयोग करना एक बुरा विचार है। – Dani

+0

@Dani - वे दो अलग-अलग विचार थे, समय में कोई थ्रेडिंग शामिल नहीं होता है ... – dfb

+0

वे कहते हैं कि आप स्टडीउट (और stderr) के पीआईपीई के साथ संयोजन में प्रतीक्षा() और मतदान() दोनों के साथ एक मृत-लॉक रख सकते हैं। । – danger89

9

एक पोर्टेबल ढंग से एक उपप्रक्रिया की एक स्ट्रिंग stdout/stderr में सांत्वना और कब्जा करने के लिए मुद्रित करने के लिए:

from StringIO import StringIO 

fout, ferr = StringIO(), StringIO() 
exitcode = teed_call(["the", "command"], stdout=fout, stderr=ferr) 
stdout = fout.getvalue() 
stderr = ferr.getvalue() 

जहां teed_call()Python subprocess get children's output to file and terminal?

में परिभाषित किया गया है आप किसी भी फ़ाइल की तरह वस्तुओं इस्तेमाल कर सकते हैं (.write() विधि)।

+0

पोस्टर स्टडआउट/stderr से डेटा को संसाधित करना चाहता है क्योंकि यह कमांड के अंत में नहीं आता है। –

+0

@ थॉमसवेंडरस्टिचले: लिंक पर क्लिक करें और 'कॉल()' परिभाषा देखें। यह जितनी जल्दी हो सके stdout/stderr प्रदर्शित करता है। यह 'subprocess.call()' नहीं है। – jfs

+6

यह काम नहीं करता है, कम से कम हमेशा नहीं: 'विशेषता त्रुटि: स्ट्रिंगियो इंस्टेंस में कोई विशेषता नहीं है' fileno'' – KomodoDave

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

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