2013-08-24 4 views
11

Я столкнулся с несколько необычной ситуацией. Я пытаюсь сценарий интерактивной консоли (для целей обучения/тестирования), и я попытался следующие:Где находится интерактивная подсказка «>>>» Python?

$ 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 не печатается, так четко все остальное было на stderr. Все идет нормально. Но тогда мы перенаправлять stderr:

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

Как приглашение печататься в обоих случаях?

EDIT: перенаправление как stdout, так и stderr ничего не может быть напечатано. Таким образом, Python явно «выбирает» один из stdout или stderr. Означает ли это, что это произошло? Я не мог понять, как это делается в исходном коде Python.

+2

Да, это странно. Возможно, он проверяет 'isatty'? – delnan

+0

Это было бы моим догадком, но я не могу понять, где именно это делает Python. Самое странное, что 'PyOS_StdioReadline', функция, которая, как представляется, отвечает за чтение ввода, жестко запрограммирована для вывода приглашения на' stderr'. Если 'stderr' были перенаправлены на' stdout', как следует из второго примера, мы должны увидеть баннер. – nneonneo

+1

Возможно, было бы проще использовать инструмент, предназначенный для обучения Python, например [особенность ноутбука ipython] (http://ipython.org/notebook.html). –

ответ

4

Похоже, питон проверяет, находится ли stdout является 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 от Parser/myreadline.c вокруг линии 194.

Вполне возможно, что переводчик импортирует readline модуля при запуске, в этом случае PyOS_ReadlineFunctionPointer будет должен быть установлен в call_readline, который использует библиотеку readline. В частности, он вызывает rl_callback_handler_install. Документация этой функции не указывает, где распечатывается приглашение, но возможно, что он проверяет, stdout/stderr: tty s.

+0

Прямо над этим, похоже, для 'PyOS_ReadlineFunctionPointer' для' PyOS_StdioReadline' (за исключением VMS, на котором я определенно не включен). – nneonneo

+0

@nneonneo Да, я немного озадачен, но это единственная ссылка, которую я могу найти, которая может каким-то образом объяснить поведение, которое вы видите. У вас есть библиотека readline? Потому что в начале файла он упоминает, что он использует его, когда он доступен. – Bakuriu

+0

@nneonneo Он устанавливает его, только если это не 'NULL'. Если интерпретатор импортирует 'readline' во время запуска, тогда модуль' readline' будет устанавливать свою функцию (см. Функцию init в 'Modules/readline.c'), и, таким образом,' PyOS_Readline' не будет использовать 'PyOS_StdioReadline'. – Bakuriu

Смежные вопросы