Không có câu trả lời nào ở đây giải quyết tất cả các nhu cầu của tôi.
- Không có chủ đề cho thiết bị xuất chuẩn (không có Hàng đợi, v.v.)
- Không chặn vì tôi cần kiểm tra những thứ khác đang diễn ra
- Sử dụng PIPE khi tôi cần để thực hiện nhiều việc, ví dụ đầu ra luồng, ghi vào tệp nhật ký và trả về một bản sao chuỗi của đầu ra.
Một chút nền tảng: Tôi đang sử dụng một ThreadPoolExecutor để quản lý một nhóm các luồng, mỗi luồng khởi chạy một tiến trình con và chạy chúng đồng thời. (Trong Python2.7, nhưng điều này cũng sẽ hoạt động trong 3.x mới hơn). Tôi không muốn sử dụng các luồng chỉ để thu thập đầu ra vì tôi muốn càng nhiều càng tốt cho các thứ khác (một nhóm gồm 20 quy trình sẽ sử dụng 40 luồng chỉ để chạy; 1 cho luồng xử lý và 1 cho đầu ra ... và nhiều hơn nữa nếu bạn muốn stderr tôi đoán)
Tôi đang gỡ lại rất nhiều ngoại lệ và như vậy ở đây vì vậy điều này dựa trên mã hoạt động trong sản xuất. Hy vọng tôi đã không làm hỏng nó trong bản sao và dán. Ngoài ra, thông tin phản hồi rất hoan nghênh!
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
Tôi chắc chắn có thêm chi phí được thêm vào đây nhưng nó không phải là vấn đề đáng lo ngại trong trường hợp của tôi. Về mặt chức năng nó làm những gì tôi cần. Điều duy nhất tôi chưa giải quyết được là tại sao điều này hoạt động hoàn hảo cho các thông điệp tường trình nhưng tôi thấy một số print
tin nhắn xuất hiện sau đó và tất cả cùng một lúc.