How do you read from stdin?
我正在尝试进行一些代码高尔夫挑战,但它们都需要从
您可以使用
1 2 3 4 | import fileinput for line in fileinput.input(): pass |
注:
有几种方法可以做到。
sys.stdin 是一个类似文件的对象,如果您想读取所有内容或想读取所有内容并自动用换行符拆分,可以在其上调用函数read 或readlines 。(您需要使用import sys 才能工作。)如果要提示用户输入,可以在python 2.x中使用
raw_input ,在python 3中只使用input 。如果实际上只想读取命令行选项,可以通过sys.argv列表访问它们。
您可能会发现这篇关于Python中I/O的wikibook文章也是一个有用的参考资料。
1 2 3 4 | import sys for line in sys.stdin: print line |
python还有内置的函数
例如,
1 | name = raw_input("Enter your name:") # Python 2.x |
或
1 | name = input("Enter your name:") # Python 3 |
下面是学习python的内容:
1 2 3 | import sys data = sys.stdin.readlines() print"Counted", len(data),"lines." |
在UNIX上,您可以通过执行以下操作来测试它:
1 2 | % cat countlines.py | python countlines.py Counted 3 lines. |
在Windows或DOS上,您可以:
1 2 | C:\> type countlines.py | python countlines.py Counted 3 lines. |
其他人提出的答案:
1 2 | for line in sys.stdin: print line |
它非常简单,而且是Python式的,但是必须注意的是,在开始迭代输入行之前,脚本将一直等到EOF。
这意味着
这种用例的正确脚本是:
1 2 3 4 5 6 7 8 9 10 | while 1: try: line = sys.stdin.readline() except KeyboardInterrupt: break if not line: break print line |
更新从注释中可以清楚地看到,在python 2上,可能只涉及缓冲,因此在发出打印调用之前,您最终会等待缓冲区填充或EOF。
How do you read from stdin in Python?
I'm trying to do some of the code golf challenges, but they all require the input to be taken from stdin. How do I get that in Python?
Ok.
你可以使用:好的。
sys.stdin —一个类似对象的文件—调用sys.stdin.read() 来读取所有内容。input(prompt) —将它作为一个可选的提示传递给输出,它从stdin读取到第一个换行符,并将其剥离。你必须重复这样做才能得到更多的线,在输入结束时,它会提高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()) 一样使用。
当然,
例如,如果将数据传输到stdin,您只需要从
1 2 | $ echo foo | python -c"import sys; print(sys.stdin.read())" foo |
文件示例
假设您有一个文件,
1 | python -c"import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt |
更长的答案
这里有一个完整的、易于复制的演示,使用了两种方法:内置函数
首先,让我们创建一个输入文件:好的。
1 2 3 | $ python -c"print('foo bar baz')"> inputs.txt |
使用我们已经看到的代码,我们可以检查是否创建了文件:好的。
1 2 3 4 | $ python -c"import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt foo bar baz |
下面是python 3对
1 2 3 4 5 | 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 3中使用
1 2 3 4 5 | $ python -c"print('try: while True: print(input()) except EOFError: pass')"> stdindemo.py |
让我们把它打印出来,以确保它符合我们的预期:好的。
1 2 3 4 5 6 | $ python -c"import sys; sys.stdout.write(sys.stdin.read())" < stdindemo.py try: while True: print(input()) except EOFError: pass |
同样,
当
在Linux/Unix上,我们可以从cat:好的。
1 2 3 4 | $ cat inputs.txt | python -m stdindemo foo bar baz |
或者我们可以直接从stdin重定向文件:好的。
1 2 3 4 | $ python -m stdindemo < inputs.txt foo bar baz |
我们还可以将模块作为脚本执行:好的。
1 2 3 4 | $ python stdindemo.py < inputs.txt foo bar baz |
下面是关于python 3内置的
1 2 3 4 5 6 7 8 | 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. |
这里我们使用
1 2 3 | $ python -c"print('import sys for line in sys.stdin: sys.stdout.write(line)')"> stdindemo2.py |
把它打印出来以确保它看起来正确:好的。
1 2 3 4 | $ python -c"import sys; sys.stdout.write(sys.stdin.read())" < stdindemo2.py import sys for line in sys.stdin: sys.stdout.write(line) |
并将输入重定向到文件中:好的。
1 2 3 4 | $ python -m stdindemo2 < inputs.txt foo bar baz |
高尔菲德指挥:好的。
1 2 3 4 | $ python -c"import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt foo bar baz |
高尔夫文件描述符
由于
如果这在你的系统上有效,它将删除更多的字符。好的。
1 2 3 4 | $ python -c"open(1,'w').write(open(0).read())" < inputs.txt baz bar foo |
python 2的
1 2 3 4 | $ python -c"from io import open; open(1,'w').write(open(0).read())" < inputs.txt foo bar baz |
处理其他意见和答案
一条注释建议使用
1 2 | ''.join(sys.stdin) sys.stdin.read() |
最重要的答案是:好的。
1 2 3 4 | import fileinput for line in fileinput.input(): pass |
但是,由于
1 2 3 4 | import sys for line in sys.stdin: pass |
另一个答案确实表明了这一点。请记住,如果在解释器中执行此操作,那么如果在Linux或Mac上,则需要执行ctrl d;如果在Windows上,则需要执行ctrl zabbkbd(在enter之后),以便将文件结尾字符发送到进程。另外,这个答案也暗示了 这将使标准输入与标准输出相呼应:
'
1 2 3 4 5 | import sys line = sys.stdin.readline() while line: print line, line = sys.stdin.readline() |
在使用
1 2 3 4 | import sys f = open(sys.argv[1]) if len(sys.argv) > 1 else sys.stdin for line in f: # Do your stuff |
并将其用作
1 | $ python do-my-stuff.py infile.txt |
或
1 | $ cat infile.txt | python do-my-stuff.py |
甚至
1 | $ python do-my-stuff.py < infile.txt |
这将使您的python脚本的行为类似于许多GNU/Unix程序,如
下面的代码芯片将帮助您(它将把所有stdin阻塞读取到
1 2 3 | import sys input_str = sys.stdin.read() print input_str.split() |
示例与Python版本2和3兼容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #!/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。使用
1 | echo 'foo bar' | ./above-script.py |
&emsp;或更短,用这里的字符串替换
1 | ./above-script.py <<< 'foo bar' |
2。使用文件名参数
1 2 | echo 'foo bar' > my-file.data ./above-script.py my-file.data |
三。通过特殊文件名
1 | echo 'foo bar' | ./above-script.py - |
您可以从stdin读取,然后将输入存储到"data"中,如下所示:
1 2 3 | data ="" for line in sys.stdin: data += line |
试试这个:
1 2 3 | import sys print sys.stdin.read().upper() |
并检查:
1 | $ echo"Hello World" | python myFile.py |
我很惊讶到目前为止还没有人提到这个黑客:
1 | python -c"import sys;print (''.join([l for l in sys.stdin.readlines()]))" |
与python2和python3兼容
从
,用
解决方案是,如果检测到Windows+python 2,则将模式设置为二进制,在python 3上使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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 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() |
我有解决问题的办法
1 2 3 4 | import sys for line in sys.stdin: print(line) |
如果不向stdin传递任何数据,它将永远阻塞。这就是我喜欢这个答案的原因:首先检查stdin上是否有数据,然后阅读它。这就是我最后所做的:
1 2 3 4 5 6 7 8 9 10 | 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) |
我在让它工作时遇到了一些问题,因为我无法读取连接到它的套接字。当套接字关闭时,它开始在活动循环中返回空字符串。所以这是我的解决方案(我只在Linux中测试过,但希望它能在所有其他系统中工作)
1 2 3 4 5 6 7 | import sys, os sep=os.linesep while sep == os.linesep: data = sys.stdin.readline() sep = data[-len(os.linesep):] print '>"%s"' % data.strip() |
因此,如果您开始监听套接字,它将正常工作(例如在bash中):
1 | while :; do nc -l 12345 | python test.py ; done |
您可以使用telnet或将浏览器指向localhost:12345来调用它。
关于这一点:
我刚刚在python 2.7上(根据别人的建议)尝试了一个非常大的文件,我不推荐它,正是因为上面提到的原因(很长时间内没有发生任何事情)。
最后我得到了一个稍微多一点的Python式解决方案(它适用于更大的文件):
1 2 | with open(sys.argv[1], 'r') as f: for line in f: |
然后我可以在本地运行脚本,如下所示:
1 | python myscript.py"0 1 2 3 4..." # can be a multi-line string or filename - any std.in input will work |
1 2 3 | n = int(raw_input()) for i in xrange(n): name, number = raw_input().split() |
有