您如何从 stdin 阅读?

我正在尝试进行一些代码挑战,但是它们都要求输入来自stdin 。我如何在 Python 中得到它?

答案

您可以使用fileinput模块:

import fileinput

for line in fileinput.input():
    pass

fileinput将循环输入指定为命令行参数中给定的文件名的输入中的所有行,如果没有提供参数,则返回标准输入。

注意: line包含尾随换行符;删除它使用line.rstrip()

有几种方法可以做到。

  • sys.stdin是一个类似于文件的对象,如果您想读取所有内容或要读取所有内容并自动按换行符对其进行拆分,可以在其上调用readreadlines函数。 (您需要import sys才能起作用。)

  • 如果要提示用户输入,可以在 Python 2.X 中使用raw_input ,而在 Python 3 中只是input

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

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

import sys

for line in sys.stdin:
    print(line)

请注意,这将在末尾包含换行符。要最后删除换行符,请使用 @brittohalloran 所说的line.rstrip()

Python 还具有内置函数input()raw_input() 。请参阅 “ 内置函数”下的 Python 文档。

例如,

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

要么

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

来自学习 Python

import sys
data = sys.stdin.readlines()
print "Counted", len(data), "lines."

在 Unix 上,您可以通过执行以下操作对其进行测试:

% cat countlines.py | python countlines.py 
Counted 3 lines.

在 Windows 或 DOS 上,您可以执行以下操作:

C:\> type countlines.py | python countlines.py 
Counted 3 lines.

其他人提出的答案:

for line in sys.stdin:
  print line

是非常简单且具有 Python 风格的代码,但必须注意,脚本将等到 EOF 才开始对输入行进行迭代。

这意味着tail -f error_log | myscript.py将无法按预期处理行。

这种用例的正确脚本是:

while 1:
    try:
        line = sys.stdin.readline()
    except KeyboardInterrupt:
        break

    if not line:
        break

    print line

更新
从注释中可以看出,仅在 python 2 上可能涉及缓冲,因此您最终在发出打印调用之前等待缓冲区填充或 EOF。

您如何从 Python 的 stdin 中读取信息?

我正在尝试进行一些代码挑战,但是它们都要求输入来自 stdin。我如何在 Python 中得到它?

您可以使用:

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

当然,必须分别导入sysfileinput

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

例如,如果您将数据通过管道传输到 stdin,则只需read sys.stdin即可:

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

我们可以看到sys.stdin处于默认文本模式:

>>> import sys
>>> sys.stdin
<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>

文件示例

假设您有一个文件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 中open (不是 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) - 在末尾添加一个'\n' from __future__ import print_function使用print(line, end='')代替(如果在 Python 2 中,则需要from __future__ import print_function )。

真正的用例进行fileinput是在一系列文件的阅读。

这会将标准输入回显到标准输出:

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

如果使用至少一个参数,则还可以使用sys.stdin在所有sys.stdin上进行sys.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

argparse是一个简单的解决方案

与 Python 第 2 版和第 3 版兼容的示例:

#!/usr/bin/python

import argparse
import sys

parser = argparse.ArgumentParser()

parser.add_argument('infile',
                    default=sys.stdin,
                    type=argparse.FileType('r'),
                    nargs='?')

args = parser.parse_args()

data = args.infile.read()

您可以通过多种方式运行此脚本:

1. 使用stdin

echo 'foo bar' | ./above-script.py

或者通过更换更短的echo通过 字符串

./above-script.py <<< 'foo bar'

2. 使用文件名参数

echo 'foo bar' > my-file.data
./above-script.py my-file.data

3. 使用stdin通过特殊的文件名-

echo 'foo bar' | ./above-script.py -