你怎么读斯坦丁?

时间:2009-09-20 05:48:07

标签: python stdin

我正在尝试执行一些code golf挑战,但它们都需要从stdin获取输入。我如何在Python中获得它?

23 个答案:

答案 0 :(得分:874)

您可以使用fileinput模块:

import fileinput

for line in fileinput.input():
    pass

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

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

答案 1 :(得分:652)

有几种方法可以做到。

  • sys.stdin是一个类似文件的对象,如果您想要阅读所有内容或想要阅读所有内容并将其拆分,则可以在其中调用函数readreadlines换行自动。 (您需要import sys才能实现此目的。)

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

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

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

答案 2 :(得分:377)

import sys

for line in sys.stdin:
    print line

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

答案 3 :(得分:204)

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

例如,

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

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

答案 4 :(得分:176)

来自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.

答案 5 :(得分:92)

其他人提出的答案:

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

<强>更新
从注释中可以看出,在python 2中只有可能涉及缓冲,因此在发出打印调用之前,你最终会等待缓冲区填充或EOF。

答案 6 :(得分:75)

  

你如何从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

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

例如,如果将数据传输到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.

内置函数,input(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)但实际上比sys.stdin.read()更长 - 而且Python必须在内存中创建一个额外的列表(这就是str.join在未给出列表时的工作方式) - for对比:

''.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 (在 Enter 之后)将结束文件字符发送到进程。此外,该答案建议print(line) - 在最后添加'\n' - 使用print(line, end='')代替(如果在Python 2中,则需要from __future__ import print_function)。

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

答案 7 :(得分:35)

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

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

答案 8 :(得分:30)

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

答案 9 :(得分:14)

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

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

答案 10 :(得分:13)

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替换为here string

或更短:

./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 :(得分:7)

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

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

答案 12 :(得分:7)

试试这个:

import sys

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

并检查:

$ echo "Hello World" | python myFile.py

答案 13 :(得分:6)

到目前为止,没有人提到这个黑客,我感到非常惊讶:

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

兼容python2和python3

答案 14 :(得分:5)

sys.stdin读取,但要在Windows上读取二进制数据,您需要格外小心,因为sys.stdin在文本模式下打开并且会损坏{ {1}}将其替换为\r\n

解决方案是在检测到Windows + Python 2时将模式设置为二进制,并在Python 3上使用\n

sys.stdin.buffer

答案 15 :(得分:4)

我对解决方案的问题

import sys

for line in sys.stdin:
    print(line)

如果你没有将任何数据传递给stdin,它将永远阻止。这就是我喜欢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)

答案 16 :(得分:2)

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

答案 17 :(得分:2)

我使用以下方法,它从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

答案 18 :(得分:1)

关于这个:

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

答案 19 :(得分:1)

n = int(raw_input())
for i in xrange(n):
    name, number = raw_input().split()

答案 20 :(得分:0)

os.read(0, x) 从代表标准输入的0读取xbytes。这是一个无缓冲的读取,比sys.stdin.read()低得多的级别

答案 21 :(得分:0)

对于 Python 3 ,应为:

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ResetsPasswords;

use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use Illuminate\Auth\Events\PasswordReset;

class ResetPasswordController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Password Reset Controller
    |--------------------------------------------------------------------------
    |
    | This controller is responsible for handling password reset requests
    | and uses a simple trait to include this behavior. You're free to
    | explore this trait and override any methods you wish to tweak.
    |
    */

    use ResetsPasswords;

    /**
     * Where to redirect users after resetting their password.
     *
     * @var string
     */
    protected $redirectTo = '/home';

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest');
    }


    protected function resetPassword($user, $password)
    {
        $user->password = Hash::make($password);

        $user->setRememberToken(Str::random(60));

        $user->save();

        event(new PasswordReset($user));

        return redirect('login');
    }
}

这基本上是cat(1)的一种简单形式,因为它不会在每行之后添加换行符。您可以使用它(使用# Filename e.g. cat.py import sys for line in sys.stdin: print(line, end="") 将文件标记为可执行文件后,例如:

chmod +x cat.py

答案 22 :(得分:0)

在使用-c命令时,以一种棘手的方式,您无需阅读stdin(在某些情况下更为灵活),就可以通过将shell脚本命令传递给python命令来代替在以$符号开头的括号内用引号引起来的sell命令。

例如

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

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