如何从命令行向Python的sys.stdin发送EOF?CTRL-D无效。

6
我正在Unix命令行上向我的Python进程写入内容。我想要发送EOF(或以某种方式刷新stdin缓冲区,以便Python可以读取我的输入)。
如果我按CTRL-C,则会出现KeyboardError错误。
如果我按CTRL-D,则程序只会停止。
如何刷新stdin缓冲区?

2
大多数终端的工作方式是,一旦您按下Enter键,您的输入就会被发送到Python。 - Jason Orendorff
如果您想更改其工作方式,Python必须更改终端设置,这是黑魔法... 可以查看termios模块吗?http://docs.python.org/library/termios.html - Jason Orendorff
4个回答

14

按下 Control-D 键不应该让你的程序“突然停止”——它应该关闭标准输入,如果你的程序正确处理了这种情况,它还可以继续运行!

例如,考虑以下 st.py 代码:

import sys

def main():
  inwas = []
  for line in sys.stdin:
    inwas.append(line)
  print "%d lines" % len(inwas),
  print "initials:", ''.join(x[0] for x in inwas)

if __name__ == '__main__':
  main()

我们可能看到类似于:

$ python st.py
nel mezzo del cammin di nostra vita
mi ritrovai per una selva oscura
che la diritta via era smarrita
3 lines initials: nmc
$ 

如果在第三行的回车后立即按下Ctrl+D,程序会意识到标准输入已完成,并执行所需的后处理,一切都很整洁和合理。

如果你的程序在Ctrl+D上提前退出,那么它肯定是编写得不好--为什么不编辑你的问题添加一个最小的可能出错的程序呢?这样我们就可以向你展示你错在了哪里。


2
如果您使用 'for l in sys.stdin',则会缓存数据。
可以使用以下代码替代:
  while 1:
     l = sys.stdin.readline()

无论如何都是缓冲的。两者之间没有区别。 - Jason Orendorff
实际上,以上对我起作用了。我想我在邮件列表上读到过,“for l in sys.stdin”有一个额外的内部缓冲区,而“sys.stdin.readline()”则没有。 - Joseph Turian
2
@JasonOrendorff:实际上,由于预读缓冲区错误,Python 2上有所不同。您可以使用for line in iter(sys.stdin.readline, ''):来解决它。尝试运行cat | python2 -u -c"<use sys.stdin or sys.stdin.readline() here>"并键入一些输入。 readline()变体导致行立即可用。 - jfs

2
我想我知道发生了什么事情。你按下了ctrl-D而没有按下enter键。如果您想将一行发送到程序,请只需按回车键。如果您按下ctrl-D而没有按下enter,则可以再次按下ctrl-D,然后您的程序应该会看到该行。在这种情况下(连续两个ctrl-D),您的程序将不会看到该行末尾的换行符。
例如,假设我有一个Python脚本a.py:
import sys

for line in sys.stdin:
    sys.stdout.write('%s' % line)

然后我执行它:

$ python a.py

然后输入以下内容:

line 1
line 2<ctrl-D><ctrl-D>

程序将打印:

line 1
line 2$

$ 是 shell 提示符。下面是使用上述输入的完整会话:

$ python a.py
line 1
line 2 line1
line 2$

(粗体 显示程序的输出。罗马字母用于显示我键入的内容,不包括两个 ctrl-D)

如果这不是您正在发生的事情,请告诉我们更多关于您正在做什么的信息。


1
try:
    # You might be inside the while-loop
    foo = raw_input('Spam: ') # Or whatever...
except EOFError:
    print 'And now for something completely different.'
    sys.exit()

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