यहाँ किसी भी उत्तर ने मेरी सभी जरूरतों को पूरा नहीं किया।
- स्टडआउट के लिए कोई सूत्र (कोई कतार, आदि, या तो)
- गैर-अवरोधक के रूप में मुझे अन्य चीजों के लिए जाँच करने की आवश्यकता है
- PIPE का उपयोग करें क्योंकि मुझे कई चीजें करने की ज़रूरत थी, उदाहरण के लिए आउटपुट, स्ट्रीम फ़ाइल में लिखें और आउटपुट की एक स्ट्रिंग कॉपी लौटाएं।
थोड़ी सी पृष्ठभूमि: मैं थ्रेड्स के एक पूल का प्रबंधन करने के लिए एक थ्रेडपूल एक्ज़ीक्यूटर का उपयोग कर रहा हूं, प्रत्येक एक सबप्रोसेस को लॉन्च कर रहा है और उन्हें कंसीडर चला रहा है। (Python2.7 में, लेकिन इसे नए 3.x में भी काम करना चाहिए)। मैं केवल उत्पादन के लिए थ्रेड्स का उपयोग नहीं करना चाहता क्योंकि मैं अन्य चीजों के लिए जितना संभव हो उतना उपलब्ध होना चाहता हूं (20 प्रक्रियाओं का एक पूल सिर्फ चलाने के लिए 40 थ्रेड्स का उपयोग कर रहा होगा; प्रक्रिया के धागे के लिए 1 और स्टडआउट के लिए 1 ... और अधिक अगर तुम stderr मुझे लगता है चाहते हैं)
मैं बहुत सारे अपवाद वापस ले रहा हूं और इस तरह यहां यह कोड पर आधारित है जो उत्पादन में काम करता है। उम्मीद है कि मैंने इसे कॉपी और पेस्ट में बर्बाद नहीं किया। इसके अलावा, प्रतिक्रिया बहुत बहुत स्वागत है!
import time
import fcntl
import subprocess
import time
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
# Make stdout non-blocking when using read/readline
proc_stdout = proc.stdout
fl = fcntl.fcntl(proc_stdout, fcntl.F_GETFL)
fcntl.fcntl(proc_stdout, fcntl.F_SETFL, fl | os.O_NONBLOCK)
def handle_stdout(proc_stream, my_buffer, echo_streams=True, log_file=None):
"""A little inline function to handle the stdout business. """
# fcntl makes readline non-blocking so it raises an IOError when empty
try:
for s in iter(proc_stream.readline, ''): # replace '' with b'' for Python 3
my_buffer.append(s)
if echo_streams:
sys.stdout.write(s)
if log_file:
log_file.write(s)
except IOError:
pass
# The main loop while subprocess is running
stdout_parts = []
while proc.poll() is None:
handle_stdout(proc_stdout, stdout_parts)
# ...Check for other things here...
# For example, check a multiprocessor.Value('b') to proc.kill()
time.sleep(0.01)
# Not sure if this is needed, but run it again just to be sure we got it all?
handle_stdout(proc_stdout, stdout_parts)
stdout_str = "".join(stdout_parts) # Just to demo
मुझे यकीन है कि यहां ओवरहेड जोड़ा जा रहा है लेकिन यह मेरे मामले में चिंता का विषय नहीं है। कार्यात्मक रूप से यह वही करता है जो मुझे चाहिए। केवल एक चीज जो मैंने हल नहीं की है वह यह है कि यह लॉग संदेशों के लिए पूरी तरह से काम करता है लेकिन मुझे print
बाद में और बाद में कुछ संदेश दिखाई देते हैं।