【问题标题】:Conflict between sys.stdin and input() - EOFError: EOF when reading a linesys.stdin 和 input() 之间的冲突 - EOFError:读取一行时出现 EOF
【发布时间】:2017-09-09 10:54:16
【问题描述】:

如果不引发 EOFError 异常,我无法让以下脚本工作:

#!/usr/bin/env python3

import json
import sys

# usage:
# echo '[{"testname": "testval"}]' | python3 test.py

myjson = json.load(sys.stdin)
print(json.dumps(myjson))

answer = input("> ")  # BUG: EOFError: EOF when reading a line
print(answer)

我读过这个似乎相关的问题:Python STDIN User Input Issue

我认为这告诉我需要清除标准输入缓冲区?但我不确定如何,因为print(sys.stdin.readline()) 只是输出一个换行符并且 EOFError 仍然存在。

我也尝试使用sys.stdin.flush() 方法(在这个问题中找到:Usage of sys.stdout.flush() method)虽然我仍然不明白它的作用,因为我在官方文档(3.6)中找不到它,最接近我发现是这个但它没有提到flush:https://docs.python.org/3/library/sys.html

请记住,我不是程序员,也没有 CS 教育或背景。我只是编写脚本来自动化我的部分非技术性工作。因此,如果您知道任何关于 stdin/stdout 如何在 Python 的 shell 中工作的好的初学者资源,请告诉我们。

【问题讨论】:

  • json.load(sys.stdin) 消耗了标准输入上的所有可用数据。没有什么可读的了,因此是 EOF。

标签: python python-3.x stdin


【解决方案1】:

通过管道输入,Python 将 sys.stdin 作为 FIFO 打开。否则,Python 将打开 sys.stdin 到 /dev/tty 或等效项。

您可以通过以下方式验证这一点:

import os,sys,stat
print("isatty():", sys.stdin.isatty())
print("isfifo():", stat.S_ISFIFO(os.fstat(0).st_mode))

运行两次,一次输入数据,一次不输入。

我明白了:

$ echo "Test" | ./test2.py
isatty(): False
isfifo(): True

$ ./test2.py
isatty(): True
isfifo(): False

所以你的 EOF 发生是因为 FIFO sys.stdin 打开到 is 为空。

不过,您可以将 sys.stdin 重新打开到 /dev/tty

j = json.load(sys.stdin)
print(j)

sys.stdin = open("/dev/tty")

answer = input("> ")
print(answer)

这会很好:

$ echo '{"key":"val"}' | python3 ./testjson.py
{'key': 'val'}
> testing
testing

【讨论】:

  • 哈哈我应该把“不是程序员”部分加粗,我需要研究很多东西才能理解发生了什么,但它工作得很好。非常感谢您的解释和解决方案!
  • 请不要担心得不到这个(真的)。这种事情很少出现,当它出现时令人难以置信的混乱。
  • 非常感谢@jedwards,我希望 SO 和 Google 先显示您的答案,然后再花几个小时寻找您的出色解决方案 :)
【解决方案2】:

您无法真正“清除”标准输入 (stdin)。它在那里,可供读取,并且许多输入函数读取到文件结束(EOF,或标准输入结束)。 “flush”操作用于标准输出。

在您的情况下,json.load(sys.stdin) 操作将读取整个标准输入(然后将其关闭)。此时,没有更多的输入可用。

如果您既要读取输入数据又要从用户那里获得交互式输入,请考虑从文件中读取数据并仅将标准输入用于交互式用户输入。

【讨论】:

  • 感谢您的详尽解释!我正在编写一个脚本,该脚本需要在将 JSON 字符串导出到标准输出的第三方程序之后执行。而且我无法更改此第三方程序的运行方式(例如,通过使其将 JSON 写入文件)。但我还需要用户手动接受一些 JSON 字典并丢弃其他字典。有没有办法在 Python 中做类似的事情?
  • 也许您将第三方脚本的 JSON 输出通过管道传输到一个临时文件,然后将该文件提供给您的程序。在 Python 或任何语言中,您通常不能使用标准输入来读取文件和读取用户输入。
猜你喜欢
  • 2021-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-19
  • 1970-01-01
  • 2011-05-22
  • 2012-08-31
相关资源
最近更新 更多