python输入流 - sys stdin read怎么用




你如何从Python中的标准输入读取? (13)

我试图做一些代码高尔夫的挑战,但他们都需要输入来自stdin 。 我如何在Python中获取?


你如何从Python中的标准输入读取?

我试图做一些代码高尔夫的挑战,但他们都需要输入来自stdin。 我如何在Python中获取?

您可以使用:

  • sys.stdin - 类似文件的对象 - 调用sys.stdin.read()来读取所有内容。
  • input(prompt) - 传递一个可选的提示输出,它从标准输入读取第一个换行符,并将其删除。 您必须重复执行此操作才能获得更多行,并在输入结束时引发EOFError。 (可能不适合打高尔夫球。)在Python 2中,这是rawinput(prompt)
  • open(0).read() - 在Python 3中, open接受文件描述符 (表示操作系统IO资源的整数),0是stdin的描述符。 它返回一个类似于文件的对象,如sys.stdin - 可能是您打高尔夫的最佳选择。
  • open('/dev/stdin').read() - 与open(0)类似,适用于Python 2和3,但不适用于Windows(甚至Cygwin)。
  • fileinput.input() - 通过sys.argv[1:]列出的所有文件中的行返回迭代器,如果未指定则返回stdin。 使用像''.join(fileinput.input())

当然, sysfileinput必须分别导入。

与Python 2和3,Windows,Unix兼容的快速sys.stdin示例

例如,您只需要从sys.stdin read数据,如果您将数据传递给stdin:

$ echo foo | python -c "import sys; print(sys.stdin.read())"
foo

文件示例

假设你有一个文件inputs.txt ,我们可以接受该文件并将其写回:

python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt

较长的答案

这是一个完整的,易于复制的演示,使用两种方法,内建函数, input (在Python 2中使用raw_input )和sys.stdin 。 数据未修改,因此处理是非操作。

首先,我们来创建一个输入文件:

$ python -c "print('foo\nbar\nbaz')" > inputs.txt

使用我们已经看到的代码,我们可以检查我们是否创建了该文件:

$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt 
foo
bar
baz

以下是Python 3中sys.stdin.read的帮助:

read(size=-1, /) method of _io.TextIOWrapper instance
    Read at most n characters from stream.

    Read from underlying buffer until we have n characters or we hit EOF.
    If n is negative or omitted, read until EOF.

内建函数, input (Python 2中的raw_input

内建函数input从标准input读取到新行,该行被剥离(补充print ,默认添加一个换行符)。直到获取EOF(文件结束)时才会发生这种情况,此时会引发EOFError

因此,下面是如何使用Python 3中的input (或Python 2中的raw_input )从stdin读取 - 因此我们创建了一个我们称为stdindemo.py的Python模块:

$ python -c "print('try:\n    while True:\n        print(input())\nexcept EOFError:\n    pass')" > stdindemo.py 

让我们打印出来,以确保它符合我们的预期:

$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < stdindemo.py 
try:
    while True:
        print(input())
except EOFError:
    pass

同样, input读起来直到换行符并基本上将它从行中删除。 print添加换行符。 所以当他们都修改输入时,他们的修改就会被取消。 (所以它们本质上是彼此的补充。)

input获得文件结束符时,它会引发EOFError,我们忽略它然后退出程序。

而在Linux / Unix上,我们可以通过cat来管道:

$ cat inputs.txt | python -m stdindemo
foo
bar
baz

或者我们可以重定向stdin的文件:

$ python -m stdindemo < inputs.txt 
foo
bar
baz

我们也可以将模块作为脚本执行:

$ python stdindemo.py < inputs.txt 
foo
bar
baz

以下是Python 3内置input的帮助:

input(prompt=None, /)
    Read a string from standard input.  The trailing newline is stripped.

    The prompt string, if given, is printed to standard output without a
    trailing newline before reading input.

    If the user hits EOF (*nix: Ctrl-D, Windows: Ctrl-Z+Return), raise EOFError.
    On *nix systems, readline is used if available.

sys.stdin

在这里,我们使用sys.stdin制作演示脚本。 迭代类文件对象的有效方法是使用类文件对象作为迭代器。 从这个输入写入stdout的补充方法是简单地使用sys.stdout.write

$ python -c "print('import sys\nfor line in sys.stdin:\n    sys.stdout.write(line)')" > stdindemo2.py

将其重新打印出来以确保它看起来正确:

$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < stdindemo2.py 
import sys
for line in sys.stdin:
    sys.stdout.write(line)

并将输入重定向到文件中:

$ python -m stdindemo2 < inputs.txt
foo
bar
baz

打高尔夫球成命令:

$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt
foo
bar
baz

高尔夫文件描述符

由于stdinstdout文件描述符分别为0和1,我们也可以在Python 3中传递这些描述符(不是2,并且注意我们仍然需要'w'来写入stdout)。

如果这可以在你的系统上运行,它将会刮掉更多的字符。

$ python -c "open(1,'w').write(open(0).read())" < inputs.txt
baz
bar
foo

Python 2的io.open也是如此,但是导入需要更多的空间:

$ python -c "from io import open; open(1,'w').write(open(0).read())" < inputs.txt 
foo
bar
baz

解决其他评论和答案

一个评论建议''.join(sys.stdin)但实际上比sys.stdin.read()更长 - 加上Python必须在内存中创建一个额外的列表(这是str.join在没有给出列表时的工作方式) - 用于对比:

''.join(sys.stdin)
sys.stdin.read()

最佳答案表明:

import fileinput

for line in fileinput.input():
    pass

但是,由于sys.stdin实现了包括迭代器协议在内的文件API,因此它与此相同:

import sys

for line in sys.stdin:
    pass

另一个答案确实表明这一点 请记住,如果您是在解释器中执行此操作,则需要在Linux或Mac上执行Ctrl - d ,或在Windows上执行Ctrl - z (在Enter之后),将文件结束字符发送到处理。 此外,该答案建议使用print(line) - 它为最终使用print(line, end='')添加'\n' (如果在Python 2中,则需要from __future__ import print_function )。

fileinput的真实用例是用于读取一系列文件。


Python还内置了函数input()raw_input() 。 请参阅内置函数下的Python文档。

例如,

name = raw_input("Enter your name: ")   # Python 2.x

要么

name = input("Enter your name: ")   # Python 3

下面的代码片段可以帮助你(它会将所有的stdin阻塞到EOF ,读入一个字符串):

import sys
input_str = sys.stdin.read()
print input_str.split()

sys.stdin读取 ,但要在Windows读取二进制数据 ,则需要格外小心,因为sys.stdin在文本模式下打开,并且\r\n将其替换为\n

如果检测到Windows + Python 2,则解决方案是将模式设置为二进制,并且在Python 3上使用sys.stdin.buffer

import sys

PY3K = sys.version_info >= (3, 0)

if PY3K:
    source = sys.stdin.buffer
else:
    # Python 2 on Windows opens sys.stdin in text mode, and
    # binary data that read from it becomes corrupted on \r\n
    if sys.platform == "win32":
        # set sys.stdin to binary mode
        import os, msvcrt
        msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
    source = sys.stdin

b = source.read()

你可以使用fileinput模块:

import fileinput

for line in fileinput.input():
    pass

fileinput将遍历输入中指定为命令行参数中给定的文件名的所有行,或者在未提供参数的情况下循环输入标准输入。


关于这一点:

for line in sys.stdin:

我只是在python 2.7上(根据别人的建议)尝试了一个非常大的文件,我不推荐它,正是由于上面提到的原因(很长一段时间没有发生)。

我结束了一个稍微更pythonic的解决方案(它在更大的文件上工作):

with open(sys.argv[1], 'r') as f:
    for line in f:

然后我可以在本地运行脚本:

python myscript.py "0 1 2 3 4..." # can be a multi-line string or filename - any std.in input will work

如果至少有一个参数存在,则可以使用sys.stdin基于所有参数构建一个参数文件,然后退回到stdin,否则:

import sys
f = open(sys.argv[1]) if len(sys.argv) > 1 else sys.stdin    
for line in f:
#     Do your stuff

并将其用作任一

$ python do-my-stuff.py infile.txt

要么

$ cat infile.txt | python do-my-stuff.py

甚至

$ python do-my-stuff.py < infile.txt

这会使你的Python脚本像许多GNU / Unix程序一样行为,如catgrepsed


尝试这个:

import sys

print sys.stdin.read().upper()

并检查它:

$ echo "Hello World" | python myFile.py

我有一些问题,当得到这个工作读取套接字的套接字。 当套接字关闭时,它开始在一个活动循环中返回空字符串。 所以这是我的解决方案(我只在linux中测试过,但希望它可以在所有其他系统中使用)

import sys, os
sep=os.linesep

while sep == os.linesep:
    data = sys.stdin.readline()               
    sep = data[-len(os.linesep):]
    print '> "%s"' % data.strip()

所以,如果你开始在一个套接字上侦听,它将正常工作(例如在bash中):

while :; do nc -l 12345 | python test.py ; done

你可以用telnet调用它,或者将浏览器指向localhost:12345


我遇到的问题是解决方案

import sys

for line in sys.stdin:
    print(line)

如果你没有将任何数据传递给stdin,它将永远阻塞。 这就是为什么我喜欢这个答案 :首先检查stdin上是否有一些数据,然后阅读它。 这就是我最终做的事情:

import sys
import select

# select(files to read from, files to write to, magic, timeout)
# timeout=0.0 is essential b/c we want to know the asnwer right away
if select.select([sys.stdin], [], [], 0.0)[0]:
    help_file_fragment = sys.stdin.read()
else:
    print("No data passed to stdin", file=sys.stderr)
    sys.exit(2)

有几种方法可以做到这一点。

  • sys.stdin是一个类似文件的对象,如果您想要读取所有内容或想要读取所有内容并自动将其分隔为新行,则可以在其上调用函数readreadlines 。 (你需要import sys才能工作。)

  • 如果你想提示用户输入,你可以在Python 2.X中使用raw_input ,并在Python 3中input

  • 如果您实际上只想读取命令行选项,则可以通过sys.argv列表访问它们。

您可能会发现这篇关于Python中的I / O的Wikibook文章也是一个有用的参考。


这将回应标准输入到标准输出:

import sys
line = sys.stdin.readline()
while line:
    print line,
    line = sys.stdin.readline()

n = int(raw_input())
for i in xrange(n):
    name, number = raw_input().split()




stdin