2009-09-07 32 views
34

Tôi muốn đầu ra từ thực thi Test_Pipe.py, tôi đã thử mã sau trên Linux nhưng nó không hoạt động.Làm thế nào để có được đầu ra từ subprocess.Popen()

Test_Pipe.py

import time 
while True : 
    print "Someting ..." 
    time.sleep(.1) 

Caller.py

import subprocess as subp 
import time 

proc = subp.Popen(["python", "Test_Pipe.py"], stdout=subp.PIPE, stdin=subp.PIPE) 

while True : 
    data = proc.stdout.readline() #block/wait 
    print data 
    time.sleep(.1) 

Dòng proc.stdout.readline() đã bị chặn, vì vậy không có dữ liệu in ra.

+0

Trùng lặp: http://stackoverflow.com/search?q=%5Bpython%5D+subprocess+output, http://stackoverflow.com/questions/803265/getting-realtime-output-using-subprocess, http: //stackoverflow.com/questions/1277866/python-subprocess-module-looping-over-stdout-of-child-process –

Trả lời

39

Bạn rõ ràng có thể sử dụng subprocess.communicate nhưng tôi nghĩ bạn đang tìm kiếm đầu vào và đầu ra thời gian thực.

readline đã bị chặn vì quá trình này có thể đang chờ bạn nhập. Bạn có thể đọc từng ký tự để khắc phục điều này như sau:

import subprocess 
import sys 

process = subprocess.Popen(
    cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE 
) 

while True: 
    out = process.stdout.read(1) 
    if out == '' and process.poll() != None: 
     break 
    if out != '': 
     sys.stdout.write(out) 
     sys.stdout.flush() 
+2

[bạn không cần 'process.poll()' trong trường hợp này] (http: // stackoverflow.com/a/17701672/4279). – jfs

12

Để tránh nhiều vấn đề mà luôn có thể phát sinh với đệm cho các nhiệm vụ như "nhận được đầu ra của tiến trình con đến quá trình chính trong thời gian thực", tôi luôn khuyên bạn nên sử dụng pexpect cho tất cả nền tảng không phải Windows, wexpect trên Windows, thay vì subprocess, khi các tác vụ đó được mong muốn.

+0

Cập nhật liên kết thành pexpect: https://github.com/pexpect/pexpect –

20

Đoạn mã của Nadia không hoạt động nhưng tính năng gọi bằng bộ đệm 1 byte rất được khuyến nghị. Cách tốt hơn để làm điều này sẽ được thiết lập các mô tả tập tin stdout để nonblocking sử dụng fcntl

fcntl.fcntl(
    proc.stdout.fileno(), 
    fcntl.F_SETFL, 
    fcntl.fcntl(proc.stdout.fileno(), fcntl.F_GETFL) | os.O_NONBLOCK, 
) 

và sau đó sử dụng lựa chọn để kiểm tra nếu các dữ liệu đã sẵn sàng

while proc.poll() == None: 
    readx = select.select([proc.stdout.fileno()], [], [])[0] 
    if readx: 
     chunk = proc.stdout.read() 
     print chunk 

Cô đúng ở chỗ vấn đề của bạn phải khác với những gì bạn đã đăng khi Caller.py và Test_Pipe.py hoạt động như được cung cấp.

+0

Nó sẽ không tạo ra kết quả sớm hơn mã trong câu hỏi do [vấn đề chặn khối.Xem câu trả lời của tôi] (http://stackoverflow.com/a/17701672/4279). – jfs

+0

Mã này tạo ra đầu ra theo thời gian thực. Bạn có gặp vấn đề với nó không? –

+0

theo liên kết trong nhận xét. – jfs

7

Test_Pipe.py đệm của nó stdout theo mặc định vì proc trong Caller.py không thấy bất kỳ đầu ra cho đến khi bộ đệm của trẻ có đầy đủ (nếu kích thước bộ đệm là 8KB thì phải mất khoảng một phút để điền Bộ đệm stdout của Test_Pipe.py).

Để làm cho đầu ra không bị chặn (dòng đệm cho dòng văn bản), bạn có thể chuyển -u flag cho tập lệnh Python con. Nó cho phép đọc subprocess' dòng đầu ra bởi dòng trong 'thời gian thực':

import sys 
from subprocess import Popen, PIPE 

proc = Popen([sys.executable, "-u", "Test_Pipe.py"], stdout=PIPE, bufsize=1) 
for line in iter(proc.stdout.readline, b''): 
    print line, 
proc.communicate() 

Xem các liên kết trong Python: read streaming input from subprocess.communicate() về cách giải quyết vấn đề khối đệm cho tiến trình con không Python.

+1

Một lần nữa bạn đang sử dụng bộ đệm 1 byte cực kỳ kém hiệu quả. –

+4

@DerrickPetzold: sai. 'bufsize = 1' có nghĩa là" line-buffered ". Nó sử dụng cùng kích thước bộ đệm như 'bufsize = -1'. Bạn có thể đã phát hiện ra rằng cả hai bình luận của bạn là sai nếu bạn thực sự chạy mã (so sánh hiệu suất thời gian và đo thời gian trước khi byte đầu tiên được đọc) – jfs

+1

tôi thích cách này vì bạn có thể in trực tiếp vào màn hình và cũng lưu trữ kết quả của popen để làm một cái gì đó với, và sau đó kiểm tra mã lỗi vv ... thumbs up =) tôi chạy nó với ra bufsize và làm việc tốt cho tôi trong mã của tôi. – pelos

Các vấn đề liên quan