sys.stdin和input()之间的冲突 - EOFError:读取一行时的EOF

时间:2017-09-09 10:54:16

标签: python python-3.x stdin

如果不抛出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

我认为这告诉我需要清除stdin缓冲区?但我不确定如何因为print(sys.stdin.readline())只输出换行符而且EOFError仍在那里。

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

请记住,我不是程序员,也不具备CS教育或背景知识。我只是编写脚本来自动化我的部分工作,否则是非技术工作。所以如果你知道有关stdin / stdout如何使用Python在shell中工作的任何好的初学者资源请告诉你。

2 个答案:

答案 0 :(得分: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打开到 为空。

但是,您可以将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

答案 1 :(得分:0)

你真的不能清楚"标准输入(stdin)。它在那里,可用于读取和许多输入功能读取直到文件结尾(EOF,或标准输入结束)。 " flush"操作用于标准输出。

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

如果您想要阅读输入数据并且具有来自用户的交互式输入,请考虑从文件中读取数据并仅使用标准输入进行交互式用户输入。