你怎么读斯坦丁?

teh*_*yan 1389 python stdin

我正在尝试做一些代码高尔夫挑战,但它们都需要输入stdin.我如何在Python中获得它?

u0b*_*6ae 906

您可以使用该fileinput模块:

import fileinput

for line in fileinput.input():
    pass
Run Code Online (Sandbox Code Playgroud)

fileinput 将循环遍历指定为命令行参数中指定的文件名的输入中的所有行,如果未提供参数则循环标准输入.

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

  • `input()` 和 `fileinput.input()` 有什么区别? (7认同)
  • 问题是关于从流中的std中读取内容。就像C中的cin (3认同)
  • 如果您希望将这些行作为列表,您可以使用“list(fileinput.input())” (3认同)
  • @AmirrezaRiahi `input()` 从标准输入读取一行,而 `fileinput.input()` 将循环遍历输入中指定为命令行参数中给出的文件名的所有行,或者标准输入(如果没有)提供了参数 (2认同)

Mar*_*off 692

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

  • sys.stdin是一个类似文件的对象,您可以在其上调用函数,read或者readlines如果您想要读取所有内容,或者您​​想要读取所有内容并自动将其拆分为换行符.(你需要import sys为此工作.)

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

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

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


小智 415

import sys

for line in sys.stdin:
    print(line)
Run Code Online (Sandbox Code Playgroud)

  • line.rstrip('\n'),否则它将删除所有空格 (5认同)
  • 删除末尾多余换行符的另一种方法是使用 print(line, end='')`。 (4认同)
  • @avp 这将无法正确处理 `\r\n` 行结尾 (3认同)

Pat*_*otz 217

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

例如,

name = raw_input("Enter your name: ")   # Python 2.x
Run Code Online (Sandbox Code Playgroud)

要么

name = input("Enter your name: ")   # Python 3
Run Code Online (Sandbox Code Playgroud)

  • 这读取了一行,这不是OP所询问的.我将这个问题解释为"如何从打开的文件句柄中读取一堆行直到EOF?" (6认同)
  • OP并不要求读取键盘输入,而是要求从stdin读取内容,在比赛情况下,stdin通常提供给参赛者。 (4认同)
  • 这就是我需要的,谷歌把我带到了这里。有趣的是,我设法对 rfid 标签、日期时间、数据库进行编码,但从未费心读取用户的输入,哈哈 (2认同)

Eug*_*ota 189

这是来自Learning Python:

import sys
data = sys.stdin.readlines()
print "Counted", len(data), "lines."
Run Code Online (Sandbox Code Playgroud)

在Unix上,您可以通过执行以下操作来测试它:

% cat countlines.py | python countlines.py 
Counted 3 lines.
Run Code Online (Sandbox Code Playgroud)

在Windows或DOS上,您可以:

C:\> type countlines.py | python countlines.py 
Counted 3 lines.
Run Code Online (Sandbox Code Playgroud)

  • "学习Python"在指导用户使用`readlines()`方面是错误的.文件对象旨在迭代而不实现内存中的所有数据. (11认同)
  • 这里使用`cat`是多余的.Unix系统的正确调用是`python countlines.py <countlines.py`. (9认同)
  • 这里有一个更有效的内存(也许更快)的方法来计算Python中的行:`print(sum(chunk.count('\n')for the block in iter(partial(sys.stdin.read,1 << 15), '')))`.[见`wc-l.py`](http://stackoverflow.com/questions/9371238/why-is-reading-lines-from-stdin-much-slower-in-c-than-python#comment11966378_9371238) (4认同)
  • @istepaniuk关于“cat的使用”,我发现使用 `cat filespec | 当我调整过滤器的命令行参数时,过滤器通常更方便,因为它们每次都会位于行尾。 (4认同)
  • @GeePokey 输入重定向也可以放在前面:`&lt; filespecfilters` (2认同)

Mas*_*meo 97

其他人提出的答案:

for line in sys.stdin:
  print line
Run Code Online (Sandbox Code Playgroud)

是非常简单和pythonic,但必须注意脚本将等到EOF开始迭代输入行.

这意味着tail -f error_log | myscript.py不会按预期处理行.

这种用例的正确脚本是:

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

    if not line:
        break

    print line
Run Code Online (Sandbox Code Playgroud)

更新
从注释中已经清除,在python 2上只有可能涉及缓冲,因此在发出打印调用之前,您最终会等待缓冲区填充或EOF.

  • @Sean:**错了**.`for sys.stdin中的行:`不会"阻塞直到EOF".有一个[Python 2中的预读错误](https://bugs.python.org/issue3907)延迟了行,直到相应的缓冲区已满.这是一个与EOF无关的缓冲问题.要解决此问题,请使用`for line in iter(sys.stdin.readline,''):`(对普通文件使用`io.open()`.你在Python 3中不需要它. (8认同)
  • sys.stdin中的`for line:`pattern __does not__等待EOF.但是如果你测试非常小的文件,响应可能会得到缓冲.测试更多数据,看它是否读取中间结果. (6认同)
  • 我怀疑这与检测libc中的tty有关,所以当你管道它检测到交互式shell时它检测到没有tty,来自expect-dev的unbuffer是一个方便的工具,我相信通过ld_preload注入一个垫片所以is_atty返回true(I怀疑它是如何处理的) (2认同)

Aar*_*all 91

你如何从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- 可能是打高尔夫球的最佳选择.
  • io.open- 类似于open('/dev/stdin').read(),适用于Python 2和3,但不适用于Windows(甚至Cygwin).
  • open(0)- 在列出的所有文件中的行上返回迭代器fileinput.input(),如果没有给出,则返回stdin.用得像sys.argv[1:].

双方''.join(fileinput.input())sys必须进口的,分别的,当然.

fileinput与Python 2和3,Windows,Unix兼容的快速示例

你只需要sys.stdinread,例如,如果你管的数据标准输入:

$ echo foo | python -c "import sys; print(sys.stdin.read())"
foo
Run Code Online (Sandbox Code Playgroud)

文件示例

假设您有一个文件,sys.stdin我们可以接受该文件并将其写回:

>>> import sys
>>> sys.stdin
<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>
Run Code Online (Sandbox Code Playgroud)

更长的答案

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

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

python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt
Run Code Online (Sandbox Code Playgroud)

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

$ python -c "print('foo\nbar\nbaz')" > inputs.txt
Run Code Online (Sandbox Code Playgroud)

这是raw_inputPython 3 的帮助:

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

内置函数,sys.stdin(sys.stdin.read在Python 2中)

内置函数input从标准输入读取到新行,该换行被剥离(补充raw_input,默认情况下会添加换行符.)这会发生,直到它获得EOF(文件结束),此时它会升高input.

因此,这里是你可以print在Python 3(或EOFErrorPython 2)中使用如何从stdin读取 - 所以我们创建一个我们称之为stdindemo.py的Python模块:

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.
Run Code Online (Sandbox Code Playgroud)

然后让我们将其打印出来以确保它符合我们的预期:

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

再次,input读取直到换行符并基本上从行中删除它.raw_input添加换行符.因此,虽然他们都修改输入,他们的修改取消.(所以他们基本上是彼此的补充.)

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

在Linux/Unix上,我们可以从cat管道:

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

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

$ cat inputs.txt | python -m stdindemo
foo
bar
baz
Run Code Online (Sandbox Code Playgroud)

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

$ python -m stdindemo < inputs.txt 
foo
bar
baz
Run Code Online (Sandbox Code Playgroud)

这是printPython 3 内置的帮助:

$ python stdindemo.py < inputs.txt 
foo
bar
baz
Run Code Online (Sandbox Code Playgroud)

input

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

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.
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

高尔夫球命令:

$ python -m stdindemo2 < inputs.txt
foo
bar
baz
Run Code Online (Sandbox Code Playgroud)

高尔夫文件描述符

由于文件描述符sys.stdinsys.stdout.write分别为0和1,我们还可以通过那些stdin在Python 3(而不是2,请注意,我们仍然需要"W"写到标准输出).

如果这适用于您的系统,它将削减更多字符.

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

Python 2 stdout也可以这样做,但导入需要更多空间:

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

解决其他意见和答案

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

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

最佳答案表明:

''.join(sys.stdin)
sys.stdin.read()
Run Code Online (Sandbox Code Playgroud)

但是,自从''.join(sys.stdin)实现文件API,包括迭代器协议,就像这样:

import fileinput

for line in fileinput.input():
    pass
Run Code Online (Sandbox Code Playgroud)

另一个答案确实表明这一点 请记住,如果你在翻译中这样做,你需要做Ctrl- d如果你在Linux或Mac上,或者Ctrl- z在Windows上(之后Enter)将文件结束字符发送到进程.此外,这个答案表明str.join- 它添加sys.stdin到最后 - 使用print(line)(如果在Python 2中,你需要'\n').

真正的用例print(line, end='')是读取一系列文件.


rli*_*lib 37

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

import sys
line = sys.stdin.readline()
while line:
    print line,
    line = sys.stdin.readline()
Run Code Online (Sandbox Code Playgroud)


Emi*_*erg 31

在所有使用的anwers上构建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
Run Code Online (Sandbox Code Playgroud)

并用它作为

$ python do-my-stuff.py infile.txt
Run Code Online (Sandbox Code Playgroud)

要么

$ cat infile.txt | python do-my-stuff.py
Run Code Online (Sandbox Code Playgroud)

甚至

$ python do-my-stuff.py < infile.txt
Run Code Online (Sandbox Code Playgroud)

这将使你的Python脚本像许多GNU/Unix程序一样cat,grepsed.


oli*_*bre 16

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()
Run Code Online (Sandbox Code Playgroud)

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

1.使用 stdin

echo 'foo bar' | ./above-script.py
Run Code Online (Sandbox Code Playgroud)

  或者echo通过在这里 替换字符串来缩短:

./above-script.py <<< 'foo bar'
Run Code Online (Sandbox Code Playgroud)

2.使用filename参数

echo 'foo bar' > my-file.data
./above-script.py my-file.data
Run Code Online (Sandbox Code Playgroud)

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

echo 'foo bar' | ./above-script.py -
Run Code Online (Sandbox Code Playgroud)


Cha*_*mar 14

以下代码片段将帮助您(它将读取所有stdin阻塞EOF到一个字符串):

import sys
input_str = sys.stdin.read()
print input_str.split()
Run Code Online (Sandbox Code Playgroud)


小智 7

试试这个:

import sys

print sys.stdin.read().upper()
Run Code Online (Sandbox Code Playgroud)

并检查:

$ echo "Hello World" | python myFile.py
Run Code Online (Sandbox Code Playgroud)


小智 7

您可以从标准输入读取,然后将输入存储到"数据"中,如下所示:

data = ""
for line in sys.stdin:
    data += line
Run Code Online (Sandbox Code Playgroud)

  • [“不依赖于CPython对a + = b或a = a + b形式的语句的就地字符串连接的有效实现。即使在CPython中,这种优化也很脆弱”](https://www.python.org / dev / peps / pep-0008 /#programming-recommendations) (3认同)

ana*_*nik 6

读取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()
Run Code Online (Sandbox Code Playgroud)


Uri*_*ren 6

我很惊讶到目前为止还没有人提到这个黑客:

python -c "import sys;print (''.join([l for l in sys.stdin.readlines()]))"
Run Code Online (Sandbox Code Playgroud)

兼容python2和python3

  • 为什么要使用分成几行的“readlines”,然后再次“join”?你可以只写“print(sys.stdin.read())” (2认同)

Ada*_*isz 5

对于Python 3来说是:

# Filename e.g. cat.py
import sys

for line in sys.stdin:
    print(line, end="")
Run Code Online (Sandbox Code Playgroud)

这基本上是 cat(1) 的简单形式,因为它不会在每行后面添加换行符。chmod +x cat.py您可以使用它(在使用以下命令标记文件可执行之后:

echo Hello | ./cat.py
Run Code Online (Sandbox Code Playgroud)


Bou*_*uni 5

我使用以下方法,它从 stdin 返回一个字符串(我将它用于 json 解析)。它适用于 Windows 上的管道和提示(尚未在 Linux 上测试)。提示时,两个换行符表示输入结束。

def get_from_stdin():

  lb = 0
  stdin = ''

  for line in sys.stdin:
    if line == "\n":
        lb += 1
        if lb == 2:
            break
    else:
        lb = 0
        stdin += line

  return stdin
Run Code Online (Sandbox Code Playgroud)


han*_*508 5

从Python 3.8开始你可以使用赋值表达式

while (line := input()):
    print(line)
Run Code Online (Sandbox Code Playgroud)