2012-05-02 13 views
5

मैं एक उपप्रोसेसर स्टडआउट पाइप से आउटपुट प्राप्त करने में कुछ कठिनाइयों में भाग रहा हूं। मैं लॉग आउटपुट निकालने के लिए, इसके माध्यम से कुछ तीसरे पक्ष कोड लॉन्च कर रहा हूं। तीसरे पक्ष के कोड के हालिया अपडेट तक, सब ठीक काम किया। अद्यतन के बाद, पायथन अनिश्चित काल तक अवरुद्ध करना शुरू कर दिया है, और वास्तव में कोई आउटपुट नहीं दिखा रहा है। मैं मैन्युअल रूप से तीसरे पक्ष के ऐप को लॉन्च कर सकता हूं और आउटपुट देख सकता हूं।विंडोज़ पर पायथन उपप्रोसेस आउटपुट?

कोड मैं उपयोग कर रहा हूँ का एक मूल संस्करण:

import subprocess, time 
from threading import Thread 

def enqueue_output(out): 
    print "Hello from enqueue_output" 
    for line in iter(out.readline,''): 
     line = line.rstrip("\r\n") 
     print "Got %s" % line 
    out.close() 

proc = subprocess.Popen("third_party.exe", stdout=subprocess.PIPE, bufsize=1) 
thread = Thread(target=enqueue_output, args=(proc.stdout,)) 
thread.daemon = True 
thread.start() 

time.sleep(30) 

यह पूरी तरह से काम करता है अगर मैं third_party.exe इस स्क्रिप्ट के लिए स्थानापन्न:

import time, sys 

while True: 
    print "Test" 
    sys.stdout.flush() 
    time.sleep(1) 

तो मैं जादू के रूप में स्पष्ट नहीं कर रहा हूँ मूल आदेश के साथ काम करने के लिए इसे करने की जरूरत है।

ये subprocess.Popen लाइन के सभी वेरिएंट मुझे कोई सफलता के साथ की कोशिश की है इस प्रकार हैं:

proc = subprocess.Popen("third_party.exe", stdout=subprocess.PIPE, bufsize=0) 
proc = subprocess.Popen("third_party.exe", stdout=subprocess.PIPE, shell=True) 
proc = subprocess.Popen("third_party.exe", stdout=subprocess.PIPE, creationflags=subprocess.CREATE_NEW_CONSOLE) 
si = subprocess.STARTUPINFO() 
si.dwFlags = subprocess.STARTF_USESTDHANDLES | subprocess.STARTF_USESHOWWINDOW 
proc = subprocess.Popen("third_party.exe", stdout=subprocess.PIPE, startupinfo=si) 

संपादित करें 1: मैं वास्तव में इस मामले में() .communicate उपयोग नहीं कर सकते। जिस ऐप को मैं लॉन्च कर रहा हूं वह लंबे समय तक चल रहा है (सप्ताहों से दिन)। एकमात्र तरीका मैं वास्तव में परीक्षण कर सकता हूं। कम्यूनिक() लॉन्च होने के तुरंत बाद ऐप को मारना होगा, जो मुझे नहीं लगता कि मुझे वैध परिणाम मिलेंगे।

यहां तक ​​कि इस के गैर पिरोया संस्करण में विफल रहता है:

import subprocess, time 
from threading import Thread 

proc = subprocess.Popen("third_party.exe", stdout=subprocess.PIPE, stderr=subprocess.PIPE) 

print "App started, reading output..." 
for line in iter(proc.stdout.readline,''): 
    line = line.rstrip("\r\n") 
    print "Got: %s" % line 

संपादित करें 2: JDI के लिए धन्यवाद, निम्नलिखित ठीक काम करता है:

import tempfile, time, subprocess 

w = "test.txt" 
f = open("test.txt","a") 
p = subprocess.Popen("third_party.exe", shell=True, stdout=f, 
         stderr=subprocess.STDOUT, bufsize=0) 

time.sleep(30) 

with open("test.txt", 'r') as r: 
    for line in r: 
     print line 
f.close() 
+0

क्या यह संभव है कि आपका तीसरा पक्ष कार्यक्रम stderr को लिखने के लिए स्विच हो? – jdi

+0

ऐसा प्रतीत नहीं होता है। अगर मैं इसके बजाय stderr को रोकता हूं, वही होता है (हालांकि, मुझे कंसोल पर ऐप का आउटपुट दिखाई देता है, लेकिन यह सिर्फ प्रिंटिंग है, यह पायथन के माध्यम से नहीं जा रहा है)। – devicenull

+0

ऐसा लगता है जैसे ऐप ने मानक आउटपुट का उपयोग करना बंद कर दिया है और सीधे कंसोल पर लिख रहा है। यदि हां, तो आप इसके बारे में बहुत कुछ नहीं कर सकते हैं। क्या आप ऐप के विक्रेता से जांच कर सकते हैं? –

उत्तर

5

सबसे पहले मैं सुझाव है कि आप इस उदाहरण को आसान बनाने में यह सुनिश्चित करने के लिए कि आप वास्तव में कुछ भी पढ़ सकते हैं। मिश्रण से धागे की जटिलता को हटाएं:

proc = subprocess.Popen("third_party.exe", stdout=subprocess.PIPE, bufsize=1) 
print proc.communicate() 

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

यदि यह काम नहीं करता है, तो क्या आपने stdout को stdr को पाइप करने का प्रयास किया है?

proc = subprocess.Popen("third_party.exe", 
         stdout=subprocess.PIPE, 
         stderr=subprocess.STDOUT, bufsize=1) 

अद्यतन

के बाद से आप कहते हैं communicate() deadlocking है, यहाँ एक और दृष्टिकोण आप अगर अपने उपप्रक्रिया के आंतरिक बफर के साथ एक समस्या को देखने के लिए कोशिश कर सकते हैं है ...

import tempfile 
import subprocess 

w = tempfile.NamedTemporaryFile() 
p = subprocess.Popen('third_party.exe', shell=True, stdout=w, 
         stderr=subprocess.STDOUT, bufsize=0) 

with open(w.name, 'r') as r: 
    for line in r: 
     print line 
w.close() 
+0

अगर मुझे थ्रेड के साथ कोई त्रुटि हुई, तो यह मेरे सरल परीक्षण ऐप के लिए क्यों काम करेगा, लेकिन वास्तविक चीज़ नहीं? मैं संवाद का उपयोग नहीं कर सकता, क्योंकि ऐप वास्तव में समाप्त नहीं होता है। यह एक सर्वर है, और लंबे समय तक चल रहा है। – devicenull

+0

@devicenull: मैं कहूंगा कि अंतर यह है कि आपकी टेस्ट स्क्रिप्ट धीरे-धीरे, हर सेकेंड 4 अक्षरों को प्रिंट कर रही है, जबकि मुझे नहीं पता कि आपका तृतीय पक्ष ऐप किस प्रकार का आउटपुट कर रहा है। आप बफर से डेडलॉकिंग हो सकते हैं। साथ ही, जब आपको इस तरह की समस्याएं होती हैं, तो जितना संभव हो उतना चर हटाने के लिए यह सर्वोत्तम होता है और सुनिश्चित करें कि प्रत्येक चरण सही तरीके से काम करता है। – jdi

+0

फ़ाइल में आउटपुट पूरी तरह से काम करता है। कोई विचार क्यों काम करता है, लेकिन पाइप नहीं करते हैं? – devicenull

2
args = ['svn','log','-v'] 

def foo(info=''): 
    import logging 
    import subprocess 
    import tempfile 
    try: 
     pipe = subprocess.Popen(args,bufsize = 0,\ 
      stdout = subprocess.PIPE,\ 
      stderr=subprocess.STDOUT) 
    except Exception as e: 
     logging.error(str(e)) 
     return False 
    while 1: 
     s = pipe.stdout.read() 
     if s: 
      print s, 
     if pipe.returncode is None: 
      pipe.poll() 
     else: 
      break 
    if not 0 == pipe.returncode: 
     return False 
    return True 

print foo() 

यह किसी को काम नहीं करना चाहिए, धागा, temp फ़ाइल जादू नहीं।

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