首页 文章

你如何从Python中读取stdin?

提问于
浏览
1235

我正在尝试做一些code golf挑战,但它们都要求输入来自 stdin . 我如何在Python中获得它?

19 回答

  • 30

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

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

    您可以使用fileinput模块:

    import fileinput
    
    for line in fileinput.input():
        pass
    

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

  • 620

    Python还有内置函数 input()raw_input() . 请参阅Built-in Functions下的Python文档 .

    例如,

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

    要么

    name = input("Enter your name: ")   # Python 3
    
  • 836
    n = int(raw_input())
    for i in xrange(n):
        name, number = raw_input().split()
    
  • 192

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

    您可以使用:

    • sys.stdin - 类文件对象 - 调用 sys.stdin.read() 来读取所有内容 .

    • input(prompt) - 将一个可选的提示符传递给输出,它从stdin读取到第一个换行符,它将被删除 . 您必须反复执行此操作才能获得更多行,在输入结束时它会引发EOFError . (可能不适合打高尔夫球 . )在Python 2中,这是 rawinput(prompt) .

    • open(0).read() - 在Python 3中 open 接受file descriptors(表示操作系统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 .

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

    例如,如果将数据传输到stdin,则只需要 read 来自 sys.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.
    

    内置函数,输入(Python 2中的raw_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) ,但's actually longer than sys.stdin.read() - plus Python must create an extra list in memory (that' s如何 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' - 改为使用 print(line, end='') (如果在Python 2中,则需要 from __future__ import print_function ) .

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

  • 169

    试试这个:

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

    并检查:

    $ echo "Hello World" | python myFile.py
    
  • 6

    其他人提出的答案:

    for line in sys.stdin:
      print line
    

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

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

    这种用例的正确脚本是:

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

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

  • 2
    import sys
    
    for line in sys.stdin:
        print line
    
  • 354

    作为这些答案的补充,您还可以使用argparse,它也向后兼容python2.7 . 兼容python2和python3的示例:

    #!/usr/bin/python
    
    import argparse
    import sys
    
    parser = argparse.ArgumentParser()
    parser.add_argument('in', default=sys.stdin, type=argparse.FileType('r'), nargs='?')
    args = parser.parse_args()
    
    data = args.in.read()
    

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

    • 使用 stdin
    echo 'foo bar' | ./above-script.py
    
    • 使用文件名参数:
    echo 'foo bar' > text-file
     ./above-script.py text-file
    
  • 35

    关于这个:

    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
    
  • 7

    当我将这个问题用于阅读通过管道传输的套接字时,我遇到了一些问题 . 当套接字关闭时,它开始在活动循环中返回空字符串 . 所以这是我的解决方案(我只在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

  • 4

    使用 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 .

  • 13

    这是Learning 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.
    
  • 8

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

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

    兼容python2和python3

  • 88

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

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

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

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

    您可能会发现this Wikibook article on I/O in Python也是一个有用的参考 .

  • 1

    您可以从stdin读取然后将输入存储到 "data" 中,如下所示:

    data = ""
    for line in sys.stdin:
        data += line
    
  • 63

    sys.stdin 读取,但是要 read binary data on 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()
    
  • 4

    我有解决方案的问题

    import sys
    
    for line in sys.stdin:
        print(line)
    

    如果你不喜欢this answer:首先检查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)
    
  • 3

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

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

相关问题