2009-10-09 20 views
12

Tập lệnh python đang kiểm soát ứng dụng bên ngoài trên Linux, truyền đầu vào thông qua một đường ống tới stdin ứng dụng bên ngoài và đầu ra đọc qua đường ống từ ứng dụng bên ngoài.Ép buộc đầu ra tiêu chuẩn của một chương trình khác được unbuffered bằng cách sử dụng Python

Vấn đề là ghi vào đường ống được đệm theo khối, và không theo hàng, và do đó sự chậm trễ xảy ra trước khi tập lệnh kiểm soát nhận dữ liệu đầu ra bằng, ví dụ, printf trong ứng dụng bên ngoài.

Không thể thay đổi ứng dụng bên ngoài để thêm các lệnh gọi fflush (0) rõ ràng.

Làm cách nào để mô-đun pty của thư viện chuẩn python được sử dụng với mô-đun subprocess để đạt được điều này?

Trả lời

-1

Thử chạy thông dịch Python với lập luận -u:

python -u myscript.py 

Điều này buộc Python sử dụng stdin unbuffered/stdout có thể giúp bạn.

+0

Cảm ơn, nhưng vấn đề là tính chất đệm của stdin/stdout của quá trình được kiểm soát, không phải của tập lệnh python. – grrussel

3

Tôi không nghĩ điều đó là có thể. Nếu ứng dụng nguồn không tuôn ra bộ đệm đi của nó, dữ liệu sẽ không đạt được bên ngoài quá trình đó cho đến khi tràn bộ đệm và một tuôn ra bị ép buộc.

Lưu ý cách một lệnh được thiết lập tốt như file có tùy chọn (-n) làm cho nó làm sạch đầu ra của nó một cách rõ ràng. Điều này là bắt buộc khi sử dụng tệp ở chế độ mà nó đọc tên tệp đầu vào từ một đường ống và in loại được phát hiện. Vì trong chế độ này, chương trình tệp không thoát khi hoàn thành, đầu ra sẽ không xuất hiện. Xem xét điều này ở mức thấp hơn: đệm đầu ra đơn giản có nghĩa là làm write() trên luồng đệm sao chép dữ liệu vào bộ đệm trong bộ nhớ, cho đến khi bộ đệm lấp đầy hoặc (thường) cho đến khi tìm thấy nguồn cấp dữ liệu. Sau đó, một phần của bộ đệm lên đến tràn hoặc linefeed được viết write() n vào bộ mô tả tệp cấp hệ thống cơ bản (có thể là một tệp, một đường ống, một ổ cắm, ...).

Tôi không hiểu làm thế nào bạn sẽ thuyết phục rằng chương trình để tuôn ra bộ đệm của nó, từ bên ngoài.

+0

Tôi tin rằng điều đó là có thể (ví dụ: http://stackoverflow.com/questions/1401002/trick-an-application-into-thinking-its-stdin-is-interactive-not-a-pipe) nhưng tôi muốn đạt được điều này trong chính kịch bản python. – grrussel

+0

@grrussel: Theo như tôi thấy, cả hai thỏa thuận với đầu vào, thay vì đầu ra. – unwind

+1

@grrussel Tôi nghĩ rằng sẽ chỉ hoạt động nếu ứng dụng đã tạo ra sự khác biệt về việc chạy tương tác hoặc theo chế độ hàng loạt ... – fortran

5

Làm điều này là có thể, nhưng giải pháp duy nhất tôi có thể nghĩ là khá phức tạp, không di động và có thể đầy những chi tiết có vấn đề. Bạn có thể sử dụng LD_PRELOAD để làm cho ứng dụng bên ngoài tải một thư viện động có chứa một hàm tạo gọi setvbuf đến stdout unbuffer. Bạn có thể cũng sẽ muốn bọc setvbuf trong thư viện để ngăn chặn ứng dụng chặn một cách rõ ràng stdout của riêng nó. Và bạn sẽ muốn bọc fwrite và printf để chúng tuôn ra trên mỗi cuộc gọi. Viết .so để được tải trước sẽ đưa bạn ra ngoài python.

+1

Tôi hiện đặt stdout thành đường ống dẫn đến chặn theo khối. Nếu tôi đã có thể thiết lập stdout cho một thiết bị đầu cuối giả thay vào đó, tôi sẽ nhận được dòng bởi đầu ra dòng. – grrussel

2

Cần lưu ý rằng một số chương trình chỉ lưu đầu ra của chúng khi chúng nghĩ rằng nó sẽ không thành "người dùng thực" (nghĩa là tty). Khi họ phát hiện ra rằng đầu ra của họ đang được đọc bởi một chương trình khác, họ đệm.

Mô phỏng tty là một trong những điều mà Expect thực hiện trong quá trình tự động hóa các quy trình khác.

Có một số pure Python implementation of Expect, nhưng tôi không biết nó xử lý tốt như thế nào với mô phỏng tty.

+0

pexpect dường như xử lý tốt điều này. Tôi tin rằng nó sử dụng thư viện pty python dưới mui xe. – krupan

6

Bạn có thể sử dụng ptys để giải quyết điều này bằng cách:

  • Tạo một pty master/slave cặp;
  • Kết nối tiêu chuẩn, stdout và stderr của quá trình con với thiết bị nô lệ pty;
  • Đọc và viết cho bậc thầy gốc trong phụ huynh.
1

Câu hỏi này hơi cũ, nhưng tôi nghĩ rằng vấn đề của bạn bây giờ có thể được giải quyết bằng cách sử dụng tiến trình con để gọi stdbuf bằng lệnh bạn muốn thực hiện.

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