Python的交互式提示符“>>>”输出到哪里?

10

我遇到了一个有些不寻常的情况。我正在尝试编写交互式控制台脚本(用于教学/测试目的),并尝试了以下操作:

$ 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
>>> 

在这两种情况下,如何打印提示?

编辑:重定向stdoutstderr会导致什么都不打印。所以 Python 明显地“选择”stdoutstderr之一。这是否有记录?我无法找出 Python 源代码中实际执行的方式。


2
哦,很奇怪。也许它检查 isatty - user395760
这可能是我猜测的,但我似乎无法弄清楚Python实际上是如何做到这一点的。最奇怪的是,PyOS_StdioReadline这个函数似乎负责读取输入,但是硬编码为将提示打印到stderr。如果像第二个示例建议的那样将stderr重定向到stdout,我们应该能看到标题栏。 - nneonneo
1
使用专门用于教授Python的工具可能会更容易,比如ipython的笔记本功能 - Burhan Khalid
1个回答

4

看起来Python会检查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);

源代码来自Parser/myreadline.c,大约在第194行左右。

有可能解释器在启动时导入了readline模块,此时PyOS_ReadlineFunctionPointer将被设置为call_readline,该函数使用readline库。特别地,它调用rl_callback_handler_install。这个函数的文档没有说明提示符是在哪里打印的,但有可能它会检查stdout/stderr是否是tty


不过,在那之上,它似乎将PyOS_ReadlineFunctionPointer设置为PyOS_StdioReadline(除了我绝对不在的VMS)。 - nneonneo
@nneonneo 是的,我有点困惑,但这是我能找到的唯一参考资料,可以在某种程度上解释您所看到的行为。您是否有可用的readline库?因为文件开头提到它在可用时使用它。 - Bakuriu
@nneonneo 只有在它不是 NULL 的时候才进行设置。如果解释器在启动期间导入了 readline 模块,那么 readline 模块将设置其函数(请参见 Modules/readline.c 中的 init 函数),因此 PyOS_Readline 将不使用 PyOS_StdioReadline - Bakuriu
啊哈!我错过了那个细节。我猜这意味着Python只作为后备将提示输出到stderr...很棒!感谢您的回答。 - nneonneo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接