2013-08-24 61 views
11

Tôi đã gặp phải một tình huống hơi bất thường. Tôi đang cố gắng để kịch bản giao diện điều khiển tương tác (cho mục đích giảng dạy/thử nghiệm), và tôi thử như sau:Đầu ra tương tác của dấu nhắc ">>>" của Python ở đâu?

$ python > /dev/null 
Python 2.7.3 (v2.7.3:70274d53c1dd, Apr 9 2012, 20:52:43) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> print 3 
>>> 

3 không được in, vì vậy rõ ràng mọi thứ khác là trên stderr. Càng xa càng tốt. Nhưng sau đó chúng tôi chuyển hướng stderr:

$ python 2> /dev/null 
>>> print 3 
3 
>>> 

Làm cách nào để được in trong cả hai trường hợp?

CHỈNH SỬA: Chuyển hướng cả hai stdoutstderr hoàn toàn không có nội dung nào được in. Vì vậy, Python rõ ràng "chọn" một trong số stdout hoặc stderr. Tài liệu đó có xảy ra không? Tôi không thể hiểu được điều này thực sự được thực hiện như thế nào trong mã nguồn Python.

+2

Huh, thật lạ lùng. Có lẽ nó kiểm tra 'isatty'? – delnan

+0

Đó là dự đoán của tôi, nhưng tôi dường như không thể tìm ra nơi Python thực sự làm điều này. Điều kỳ lạ nhất là 'PyOS_StdioReadline', hàm xuất hiện chịu trách nhiệm đọc đầu vào, được mã hóa cứng để in dấu nhắc tới' stderr'. Nếu 'stderr' được chuyển hướng đến' stdout', như ví dụ thứ hai cho thấy, chúng ta sẽ thấy biểu ngữ. – nneonneo

+1

Có thể dễ dàng hơn khi sử dụng một công cụ được thiết kế để dạy Python, như [tính năng sổ tay của ipython] (http://ipython.org/notebook.html). –

Trả lời

4

Nó có vẻ như kiểm tra python liệu stdout là một tty:

/* This is needed to handle the unlikely case that the 
* interpreter is in interactive mode *and* stdin/out are not 
* a tty. This can happen, for example if python is run like 
* this: python -i < test1.py 
*/ 
if (!isatty (fileno (sys_stdin)) || !isatty (fileno (sys_stdout))) 
    rv = PyOS_StdioReadline (sys_stdin, sys_stdout, prompt); 
else 
    rv = (*PyOS_ReadlineFunctionPointer)(sys_stdin, sys_stdout, 
             prompt); 

sourcecode từ Parser/myreadline.c xung quanh dòng 194.

Có thể là người phiên dịch nhập khẩu các mô-đun readline lúc khởi động, trong trường hợp này PyOS_ReadlineFunctionPointer sẽ được đặt thành call_readline, sử dụng thư viện readline. Cụ thể là nó gọi rl_callback_handler_install. Tài liệu của chức năng này không ghi rõ nơi dấu nhắc được in, nhưng có thể nó kiểm tra xem stdout/stderrtty s.

+0

Ngay trên đó, mặc dù, nó có vẻ để thiết lập 'PyOS_ReadlineFunctionPointer' để' PyOS_StdioReadline' (ngoại trừ trên VMS, mà tôi chắc chắn không phải trên). – nneonneo

+0

@nneonneo Vâng, tôi hơi bối rối, nhưng đây là tài liệu tham khảo duy nhất tôi có thể tìm thấy bằng cách nào đó có thể giải thích hành vi bạn thấy. Bạn có sẵn thư viện đọc không? Bởi vì ở đầu của tập tin nó đề cập rằng nó sử dụng nó khi nó có sẵn. – Bakuriu

+0

@nneonneo Nó đặt nó chỉ khi nó không phải là 'NULL'. Nếu trình thông dịch nhập 'readline' trong khi khởi động thì module' readline' sẽ thiết lập chức năng của nó (xem hàm init tại 'Modules/readline.c'), và do đó' PyOS_Readline' sẽ không sử dụng 'PyOS_StdioReadline'. – Bakuriu

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