2012-05-14 8 views
8

Tôi đang chạy một tệp thi hành C từ Python và tệp thực thi này đôi khi bị phân tách. Khi nó segfaults module subprocess không trả về bất cứ điều gì trong stdout hoặc stderr.Mô-đun con xử lý Python không trả về giá trị stdout trên segfault

Mẫu mã:

import subprocess 

proc = subprocess.Popen(['./a.out'], stdin=subprocess.PIPE, 
     stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
out, err = proc.communicate() 
print 'out: "%s"' % out 
print 'err: "%s"' % err 
print proc.returncode 

Nguồn cho a.out là:

int main() { 
    printf("hello world\n"); 
    int x = 1/0; 
} 

Kết quả của ./a.out là:

hello world 
Floating point exception 

Đầu ra của mã Python là (trong Linux , python 2.7):

out: "" 
err: "" 
-8 

Có cách nào để có được đầu ra của tệp thực thi ngay cả khi nó bị lỗi không?

Một phương pháp chung để dịch mã trả về thành chuỗi tin nhắn, cũng sẽ rất tuyệt.

Trả lời

2

Ứng dụng gần như chắc chắn không xả bộ đệm đầu ra của nó trước khi nó gặp lỗi phân đoạn.

Theo mặc định, thư viện stdio C định cấu hình bộ đệm cho stdout sao cho bộ đệm được xóa ở mọi đầu dòng, nhưng chỉ là stdout là một tty. Đó là lý do tại sao bạn làm xem kết quả khi bạn chạy a.out từ dòng lệnh.

Bạn không thể trực tiếp làm cho chương trình C thay đổi điều này từ phía Python. Nhưng những gì bạn có thể làm là cung cấp cho nó một tty để sử dụng cho stdout của nó, cụ thể là một tty giả. Chi tiết về việc mở và thiết lập thiết bị đầu cuối giả phức tạp hơn nhiều so với việc thiết lập đường ống thông thường, nhưng có một số mô-đun sẽ giúp bạn: Xem Pexpectthis SO question, trong số các loại khác.

3

Chương trình C của bạn không xóa bộ đệm đầu ra. Cách đơn giản nhất xung quanh vấn đề này là để thay đổi chế độ đầu ra của STDOUT để unbuffered:

#include <stdio.h> 
int main(int argc,char **argv) { 
    setvbuf(stdout,_IONBF,0,0); 
    printf("hello world\n"); 
    int x = 1/0; 
} 

Bây giờ chương trình của bạn (mà tôi chỉnh sửa để sửa chữa một lỗi đánh máy) sẽ cho kết quả chính xác:

$ python2.7 x.py 
out: "hello world 
" 
err: "" 
0 
$ 

Sự trở lại mã là 0 trên máy Mac của tôi, gây nhầm lẫn, bởi vì các chương trình được chấm dứt cho một tín hiệu không có mã trả về.

+0

Giải pháp tốt, nếu bạn kiểm soát mã C và có thể thêm lệnh gọi 'setvbuf' vào đó và biên dịch lại. Tôi đã giả định mã C của bên thứ ba mà nó nằm ngoài câu hỏi để sửa đổi. – Celada

+0

Vâng, nếu mã bên thứ ba của bạn không tuôn ra mã vạch của nó trước khi nó bị treo, bạn không thể làm được gì nhiều. – vy32