ไม่มีคำตอบใด ๆ ที่ตรงกับความต้องการของฉันทั้งหมด
- ไม่มีเธรดสำหรับ stdout (ไม่มีคิว ฯลฯ )
- ไม่มีการปิดกั้นเนื่องจากฉันต้องตรวจสอบสิ่งอื่น ๆ ที่เกิดขึ้น
- ใช้ PIPE ตามที่ฉันต้องการเพื่อทำสิ่งต่าง ๆ เช่นสตรีมเอาต์พุตเขียนไปยังล็อกไฟล์และส่งคืนสำเนาสตริงของเอาต์พุต
พื้นหลังเล็กน้อย: ฉันใช้ ThreadPoolExecutor เพื่อจัดการกลุ่มของเธรดแต่ละตัวเรียกใช้กระบวนการย่อยและเรียกใช้พร้อมกัน (ใน Python2.7 แต่มันควรจะทำงานใน 3.x ที่ใหม่กว่าด้วย) ฉันไม่ต้องการใช้เธรดสำหรับการรวบรวมเอาต์พุตเนื่องจากฉันต้องการให้มีมากที่สุดเท่าที่จะเป็นไปได้สำหรับสิ่งอื่น ๆ (กลุ่มของกระบวนการ 20 จะใช้ 40 เธรดเพื่อเรียกใช้ 1 สำหรับเธรดกระบวนการและ 1 สำหรับ stdout ... และอื่น ๆ ถ้าคุณต้องการ 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
ข้อความบางข้อความปรากฏขึ้นในภายหลังและทั้งหมดในครั้งเดียว