【问题标题】:How to send EOF to Python sys.stdin from commandline? CTRL-D doesn't work如何从命令行将 EOF 发送到 Python sys.stdin? CTRL-D 不起作用
【发布时间】:2009-12-12 03:54:43
【问题描述】:

我正在从 unix 上的命令行写入我的 Python 进程。我想发送 EOF(或以某种方式刷新标准输入缓冲区,以便 Python 可以读取我的输入。)

如果我按下 CTRL-C,我会得到一个 KeyboardError。

如果我按下 CTRL-D,程序就会停止。

如何刷新标准输入缓冲区?

【问题讨论】:

  • 大多数终端的工作方式,只要你按下 Enter,你的输入就会被发送到 Python。
  • 如果你想改变它的工作方式,Python 必须改变终端设置,这是黑魔法......也许看到termios 模块? docs.python.org/library/termios.html

标签: python unix command-line buffer


【解决方案1】:

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
$ 

如果在第三行输入后立即按下 control-D —— 程序意识到标准输入已完成,并执行所需的后处理,所有这些都整洁而正确。

如果您的程序在 control-D 上过早退出,则它一定是编码错误 - 编辑您的问题以添加您能想到的最小的“行为不端”程序怎么样,这样我们就可以准确地告诉您您是如何出错的?

【讨论】:

    【解决方案2】:

    如果你使用'for l in sys.stdin',它会被缓冲。

    你可以使用:

      while 1:
         l = sys.stdin.readline()
    

    【讨论】:

    • 无论如何它都被缓冲了。两者没有区别。
    • 实际上,以上内容对我有用。我想我在邮件列表中看到“for l in sys.stdin”有一个额外的内部缓冲区,而 sys.stdin.readline() 没有。
    • @JasonOrendorff:实际上,由于read-ahead buffer bug,Python 2 存在差异。您可以使用for line in iter(sys.stdin.readline, ''): 来解决它。尝试运行cat | python2 -u -c"<use sys.stdin or sys.stdin.readline() here>" 并输入一些输入。 readline() 变体导致线路立即可用。
    【解决方案3】:

    我想我知道发生了什么。您正在点击 ctrl-D 而没有点击 enter。如果要向程序发送一行,只需按 Enter。如果您点击ctrl-D 而没有点击enter,您可以再次点击ctrl-D,然后您的程序应该会看到该行。在这种情况下(连续两个ctrl-Ds),您的程序将不会在行尾看到换行符。

    例如,假设我有一个 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
    1号线
    第 2 行 第 1 行
    第 2 行$

    粗体显示程序的输出。罗马字母大小写用于显示我输入的内容,没有两个ctrl-Ds)

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

    【讨论】:

      【解决方案4】:
      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()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-14
        • 1970-01-01
        • 1970-01-01
        • 2016-03-30
        相关资源
        最近更新 更多