फिलहाल अन्य सभी उत्तरों बच्चे उपप्रोसेस पक्ष पर बफरिंग को संभाल नहीं पाते हैं यदि उपप्रोसेसर एक पायथन स्क्रिप्ट नहीं है जो -u
ध्वज स्वीकार करता है। "Q: Why not just use a pipe (popen())?" in the pexpect documentation देखें।
कुछ सी stdio- आधारित (FILE*
) प्रोग्राम के लिए -u
ध्वज अनुकरण करने के लिए आप stdbuf
कोशिश कर सकते हैं।
आप उपेक्षा अगर यह आपका उत्पादन ठीक से interleaved नहीं किया जाएगा और ऐसा दिखाई देगा: भी
stderr
stderr
...large block of stdout including parts that are printed before stderr...
आप निम्न क्लाइंट प्रोग्राम के साथ यह कोशिश कर सकते के साथ/अंतर नोटिस -u
ध्वज के बिना (['stdbuf', '-o', 'L', 'child_program']
उत्पादन ठीक करता है):
#!/usr/bin/env python
from __future__ import print_function
import random
import sys
import time
from datetime import datetime
def tprint(msg, file=sys.stdout):
time.sleep(.1*random.random())
print("%s %s" % (datetime.utcnow().strftime('%S.%f'), msg), file=file)
tprint("stdout1 before stderr")
tprint("stdout2 before stderr")
for x in range(5):
tprint('stderr%d' % x, file=sys.stderr)
tprint("stdout3 after stderr")
लिनक्स पर आप pty
का उपयोग करते हैं उपप्रक्रिया सहभागी चलाता है जैसे के रूप में ही व्यवहार प्राप्त करने के लिए कर सकता है, यहाँ एक संशोधित @T.Rojan's answer है:
import logging, os, select, subprocess, sys, pty
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
master_fd, slave_fd = pty.openpty()
p = subprocess.Popen(args,stdout=slave_fd, stderr=subprocess.PIPE, close_fds=True)
with os.fdopen(master_fd) as stdout:
poll = select.poll()
poll.register(stdout, select.POLLIN)
poll.register(p.stderr,select.POLLIN | select.POLLHUP)
def cleanup(_done=[]):
if _done: return
_done.append(1)
poll.unregister(p.stderr)
p.stderr.close()
poll.unregister(stdout)
assert p.poll() is not None
read_write = {stdout.fileno(): (stdout.readline, logger.info),
p.stderr.fileno(): (p.stderr.readline, logger.error)}
while True:
events = poll.poll(40) # poll with a small timeout to avoid both
# blocking forever and a busy loop
if not events and p.poll() is not None:
# no IO events and the subprocess exited
cleanup()
break
for fd, event in events:
if event & select.POLLIN: # there is something to read
read, write = read_write[fd]
line = read()
if line:
write(line.rstrip())
elif event & select.POLLHUP: # free resources if stderr hung up
cleanup()
else: # something unexpected happened
assert 0
sys.exit(p.wait()) # return child's exit code
यह मानता है कि stderr हमेशा unbuffered/line-buffered और stdout एक इंटरैक्टिव मोड में लाइन-buffered है। केवल पूर्ण लाइनें पढ़ी जाती हैं। आउटपुट में गैर-समाप्त लाइनें होने पर प्रोग्राम ब्लॉक हो सकता है।
क्या होगा यदि प्रोग्राम के कुछ स्टडआउट विस्मयादिबोधक बिंदु से शुरू होते हैं? – robert
क्या सभी स्टडआउट को डंप करना और फिर सभी stderr को उसी फ़ाइल में डंप करना ठीक है, या आप उन्हें अंतःस्थापित करना चाहते हैं? – robert
मैं इसे अंतःस्थापित करना चाहता हूं। – beemtee