我如何从标准输入读取?

2024-11-25 08:49:00
admin
原创
193
摘要:问题描述:我如何读取stdin?有些代码高尔夫挑战需要使用stdin输入。解决方案 1:使用fileinput模块:import fileinput for line in fileinput.input(): pass fileinput将循环遍历输入中指定为命令行参数中给出的文件名的所有行,如果...

问题描述:

我如何读取stdin?有些代码高尔夫挑战需要使用stdin输入。


解决方案 1:

使用fileinput模块:

import fileinput

for line in fileinput.input():
    pass

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

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

解决方案 2:

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

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

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

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

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

解决方案 3:

import sys

for line in sys.stdin:
    print(line)

请注意,这将在末尾包含一个换行符。要删除末尾的换行符,请line.rstrip()按照@brittohalloran 所述使用。

解决方案 4:

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

例如,

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

或者

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

解决方案 5:

以下是来自《学习 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.

解决方案 6:

如何从 Python 中的 stdin 读取?

我正在尝试完成一些代码高尔夫挑战,但它们都要求从 stdin 获取输入。如何在 Python 中实现这一点?

您可以使用:

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

  • input(prompt)- 向其传递一个可选提示以进行输出,它会从 stdin 读取到第一个换行符,并将其删除。您必须重复执行此操作才能获得更多行,在输入结束时它会引发 EOFError。(可能不适合打高尔夫球。)在 Python 2 中,这是raw_input(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())

当然,sys和都必须分别导入。fileinput

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

你只需要从readsys.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
bar
baz')" > 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.

内置函数,inputraw_input在 Python 2 中)

内置函数input从标准输入读取直到换行符,然后将其删除(补充print,默认情况下会添加换行符。)这种情况会一直持续到 EOF(文件结束),此时它会引发EOFError

因此,下面介绍了如何input在 Python 3(或raw_inputPython 2)中从 stdin 读取 - 因此我们创建一个名为 stdindemo.py 的 Python 模块:

$ python -c "print('try:
    while True:
        print(input())
except EOFError:
    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

或者我们可以从标准输入重定向文件:

$ 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
for line in sys.stdin:
    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

高尔夫文件描述符

stdin由于和的文件描述符stdout分别为 0 和 1,我们也可以将它们传递给openPython 3(而不是 2,请注意,我们仍然需要“w”来写入 stdout)。

如果这在您的系统上运行,它将减少更多字符。

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

Python 2io.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

另一个答案确实表明了这一点。只需记住,如果您在解释器中执行此操作,则需要执行Ctrl-d如果您使用的是 Linux 或 Mac,或者Ctrl-z在 Windows 上(在 之后Enter)以将文件结束字符发送到进程。此外,该答案建议-在末尾print(line)添加- 改用(如果在 Python 2 中,您需要)。`'
'print(line, end='')from future import print_function`

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

解决方案 7:

其他人提出的答案:

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 才能发出打印调用。

解决方案 8:

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

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

解决方案 9:

在所有使用答案的基础上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

解决方案 10:

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 -

解决方案 11:

下面的代码片段将帮助您(它将读取所有 stdin 阻塞到EOF,并放入一个字符串中):

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

解决方案 12:

我很惊讶到目前为止没有人提到过这个技巧:

python -c "import sys; set(map(sys.stdout.write,sys.stdin))"

在 python2 中你可以放弃set()调用,但无论哪种方式都可以

解决方案 13:

尝试一下:

import sys

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

并使用以下命令进行检查:

$ echo "Hello World" | python myFile.py

解决方案 14:

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

def get_from_stdin():

  lb = 0
  stdin = ''

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

  return stdin

解决方案 15:

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

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

解决方案 16:

从 读取sys.stdin,但要在 Windows 上读取二进制数据,您需要格外小心,因为sys.stdin以文本模式打开,并且`
用 替换它们会造成损坏
`。

解决方案是,如果检测到 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 

    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()

解决方案 17:

对于Python 3来说,将是:

# Filename e.g. cat.py
import sys

for line in sys.stdin:
    print(line, end="")

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

echo Hello | ./cat.py

解决方案 18:

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

while (line := input()):
    print(line)

解决方案 19:

我的解决方案遇到的问题

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)

解决方案 20:

当使用-c命令时,作为一种巧妙的方法,您可以将 shell 脚本命令传递给 python 命令,而不是读取stdin(在某些情况下更灵活),方法是将 shell 命令放在以符号开头的括号内的引号中$

例如

python3 -c "import sys; print(len(sys.argv[1].split('
')))" "$(cat ~/.goldendict/history)"

这将计算 goldendict 历史文件中的行数。

解决方案 21:

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

解决方案 22:

关于这一点:

for line in sys.stdin:

我刚刚在 python 2.7 上尝试过(按照别人的建议)处理一个非常大的文件,我不推荐这样做,正是由于上述原因(很长时间内没有任何反应)。

我最终得到了一个更符合 Python 风格的解决方案(并且它适用于更大的文件):

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

解决方案 23:

值得一提的是,短命令行链接比和input更受欢迎,因为它不需要导入,并且输入起来更短。fileinput`sys.stdin`

$ echo hello world | python3 -c "print(input().upper())"
HELLO WORLD

解决方案 24:


os.read(0, x)
一个从 0 开始读取 xbytes,代表 stdin。这是一个无缓冲读取,比 sys.stdin.read() 更底层

解决方案 25:

非阻塞、字节模式、标准输入 -> 标准输出:
# pipe.py

import os, sys, time

os.set_blocking(0, False)
sys.stdin = os.fdopen(0, 'rb', 0)
sys.stdout = os.fdopen(1, 'wb', 0)

while 1:
    time.sleep(.1)
    try: out = sys.stdin.read()
    except:
        sys.stdout.write(b"E")
        continue
    if out is None:
        sys.stdout.write(b"N")
        continue
    if not out:
        sys.stdout.write(b"_")
        break
    # working..
    out = b"<" + out + b">"
    sys.stdout.write(out)

sys.stdout.write(b".
")
用法:
$ for i in 1 2 3; do sleep 1; printf "===$i==="; done | python3 pipe.py
NNNNNNNNN<===1===>NNNNNNNNN<===2===>NNNNNNNNN<===3===>_.
最小代码:
import os, sys

os.set_blocking(0, False)
fd0 = os.fdopen(0, 'rb', 0)
fd1 = os.fdopen(1, 'wb', 0)

while 1:
    bl = fd0.read()
    if bl is None: continue
    if not bl: break
    fd1.write(bl)

在 Linux、Python 3.9.2 上测试

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1590  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1361  
  信创产品在政府采购中的占比分析随着信息技术的飞速发展以及国家对信息安全重视程度的不断提高,信创产业应运而生并迅速崛起。信创,即信息技术应用创新,旨在实现信息技术领域的自主可控,减少对国外技术的依赖,保障国家信息安全。政府采购作为推动信创产业发展的重要力量,其对信创产品的采购占比情况备受关注。这不仅关系到信创产业的发展前...
信创和国产化的区别   18  
  信创,即信息技术应用创新产业,旨在实现信息技术领域的自主可控,摆脱对国外技术的依赖。近年来,国货国用信创发展势头迅猛,在诸多领域取得了显著成果。这一发展趋势对科技创新产生了深远的推动作用,不仅提升了我国在信息技术领域的自主创新能力,还为经济社会的数字化转型提供了坚实支撑。信创推动核心技术突破信创产业的发展促使企业和科研...
信创工作   18  
  信创技术,即信息技术应用创新产业,旨在实现信息技术领域的自主可控与安全可靠。近年来,信创技术发展迅猛,对中小企业产生了深远的影响,带来了诸多不可忽视的价值。在数字化转型的浪潮中,中小企业面临着激烈的市场竞争和复杂多变的环境,信创技术的出现为它们提供了新的发展机遇和支撑。信创技术对中小企业的影响技术架构变革信创技术促使中...
信创国产化   19  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用