當嘗試讀取C 程式的輸出時,即「2000 ,」來自使用subprocess 的Python 腳本,該腳本掛在「for line in iter(process.stdout.readline, '')」行。儘管 C 程式不斷列印「2000」並且從未達到結束狀態,但還是會發生這種情況。
問題源自於區塊緩衝問題。預設情況下,透過管道運行的 C 程式中的 stdout(例如,當使用 subprocess.Popen 時)是塊緩衝的。這意味著在緩衝區已滿或明確刷新之前,資料不會刷新到管道。
選項1:直接修改C 程式
要解決此問題,您可以強制stdout 在C 程式中進行行緩衝:
#include <stdio.h> int main() { setvbuf(stdout, (char *) NULL, _IOLBF, 0); // Make line buffered stdout while (1) { printf("2000\n"); sleep(1); } return 0; }
選項2:使用stdbuf 實用程式
或者,您可以使用stdbuf 公用程式來變更在不修改C 程式來源的情況下緩衝類型:
from subprocess import Popen, PIPE process = Popen(["stdbuf", "-oL", "./main"], stdout=PIPE, bufsize=1) for line in iter(process.stdout.readline, b''): print(line) process.communicate()
選項3:使用偽TTY
另一種方法涉及使用偽TTY 來欺騙C 程式認為它正在交互運行:
import os import pty import sys from select import select from subprocess import Popen, STDOUT master_fd, slave_fd = pty.openpty() process = Popen("./main", stdin=slave_fd, stdout=slave_fd, stderr=STDOUT, bufsize=0, close_fds=True) timeout = .1 with os.fdopen(master_fd, 'r+b', 0) as master: input_fds = [master, sys.stdin] while True: fds = select(input_fds, [], [], timeout)[0] # Handle subprocess output and user input here
選項4:使用pexpect
Pexpect 提供了一個更高級別的接口,可以簡化偽TTY 處理:
import pexpect child = pexpect.spawn("./.main") for line in child: print(line) child.close()
以上是為什麼我的 Python `subprocess.readline` 在讀取連續編寫的 C 程式時會掛起?的詳細內容。更多資訊請關注PHP中文網其他相關文章!