web-dev-qa-db-ja.com

Stdinからどのように読みますか?

コードgolf の課題のいくつかをやろうとしていますが、それらはすべてstdinからの入力を必要とします。どうやってPythonでそれを手に入れるのですか?

1298
tehryan

fileinput モジュールを使うことができます:

import fileinput

for line in fileinput.input():
    pass

fileinput は、コマンドライン引数で指定されたファイル名として指定された入力内のすべての行、または引数が指定されていない場合は標準入力をループします。

注意:lineは末尾の改行を含みます。それを削除するにはline.rstrip()を使います

854
u0b34a0f6ae

それを行うにはいくつかの方法があります。

  • sys.stdin は、ファイルのようなオブジェクトで、すべてを読みたい場合、またはすべてを読みたい場合に、関数readまたはreadlinesを呼び出すことができ、自動的に改行で分割します。 (これを機能させるにはimport sysが必要です。)

  • 入力に プロンプト ユーザーを使いたい場合は、Python 2.Xでは raw_input を、Python 3では input を使用できます。 

  • 実際にコマンドラインオプションを読みたいだけであれば、 sys.argv listを介してそれらにアクセスできます。

あなたはおそらく このウィキブックスのPythonでのI/Oに関する記事 も参考になると思います。

636
Mark Rushakoff
import sys

for line in sys.stdin:
    print line
364
user303110

Pythonにはinput()raw_input()という組み込み関数もあります。 Pythonドキュメントの 組み込み関数 を参照してください。

例えば、

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

または

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

これは 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.
173
Eugene Yokota

他の人が提案した答え:

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ではバッファリングのみが関係している可能性があることが明らかになったので、print呼び出しが発行される前にバッファがいっぱいになるかEOFを待つことになります。

91

Pythonの標準入力からどのように読みますか?

私はいくつかのコードゴルフチャレンジをしようとしていますが、それらはすべて標準入力からの入力を必要とします。 Pythonでそれを取得するにはどうすればよいですか?

次を使用できます。

  • sys.stdin -ファイルのようなオブジェクト-sys.stdin.read()を呼び出してすべてを読み取ります。
  • input(Prompt) -オプションのプロンプトを出力に渡し、stdinから最初の改行まで読み取ります。より多くの行を取得するにはこれを繰り返し行う必要があり、入力の最後にEOFErrorが発生します。 (おそらくゴルフには向いていません。)Python 2では、これはrawinput(Prompt)です。
  • open(0).read() -In Python 3 openは受け入れます ファイル記述子 (オペレーティングシステムIOリソースを表す整数)、0はstdinsys.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にパイプする場合、sys.stdinからreadするだけです。

$ 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の2つのメソッドを使用した、簡単で複製可能な完全なデモを次に示します。データは変更されていないため、処理は非操作です。

まず、入力用のファイルを作成しましょう。

$ 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と呼ばれるPythonモジュールを作成します.py:

$ 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ではなく、stdoutに書き込むために 'w'が必要なことに注意してください)。

これがシステム上で機能する場合、より多くの文字を削除します。

$ 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

他のコメントと回答への対応

1つのコメントは''.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

別の答えdoesはこれを示唆しています。通訳でそれを行う場合、あなたがする必要があることを覚えておいてください Ctrl-d LinuxまたはMacを使用している場合、または Ctrl-z Windowsの場合(後 Enter)ファイルの終わりの文字をプロセスに送信します。また、その答えはprint(line)を示唆しています-これは'\n'を最後に追加します-代わりにprint(line, end='')を使用します(Python 2の場合、from __future__ import print_functionが必要です)。

fileinputの実際の使用例は、一連のファイルを読み取るためです。

82
Aaron Hall

これは標準入力を標準出力にエコーします。

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

sys.stdinを使用してすべてのanwersに基づいて、少なくとも1つの引数が存在する場合は引数ファイルから次のように読み取り、それ以外の場合は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スクリプトをcatgrepそしてsedのような多くのGNU/Unixプログラムのように振る舞わせるでしょう。

30
Emil Lundberg

次のコードがそれを手助けしてくれるでしょう(それはEOFへのstdinブロッキングのすべてを一つの文字列に読みます):

import sys
input_str = sys.stdin.read()
print input_str.split()
14
Chandan Kumar

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

echoherestring に置き換えて、またはそれより短くすることができます。

./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 -
8
olibre

次のように標準入力から読み、入力を "data" に格納します。

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

これを試して:

import sys

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

そして、それをチェックしてください。

$ echo "Hello World" | python myFile.py
7
Boubakr

私はこれまでこのハックについて言及していなかったことにとても驚いています。

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

python2とpython3の両方と互換性があります。

6
Uri Goren

sys.stdinから読み込みますが、Windows上で バイナリデータを読み込む にすると、sys.stdinがテキストモードで開かれ、\r\nが破損して\nに置き換えられるため、特に注意が必要です。

解決策は、Windows + Python 2が検出された場合はmodeをbinaryに設定し、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()
5

私は解決策を持っている問題

import sys

for line in sys.stdin:
    print(line)

標準入力にデータを渡さないと、永遠にブロックされてしまいます。だからこそ この答え :まず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
SummerBreeze

それにパイプでつながれたソケットを読むためにこれを機能させるとき私はいくつかの問題を抱えていました。ソケットが閉じられると、アクティブなループで空の文字列を返し始めました。だからこれは私の解決策です(私は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

2
estani

これに関して:

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
1
szeitlin

標準入力を表す0からxバイトを読み込むos.read(0, x)があります。これはバッファされていない読み込みで、sys.stdin.read()よりも低レベルです。

0
Jay

-cコマンドをトリッキーな方法として使用する場合、stdin(および場合によってはより柔軟)を読み取る代わりに、pythonコマンドにもシェルスクリプトコマンドを渡すことができます。 $記号で始まるカッコ内にセルコマンドを引用符で囲みます。

例えば.

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

これにより、goldendictの履歴ファイルの行数がカウントされます。

0
Kasrâmvd

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
0
AdamKalisz
n = int(raw_input())
for i in xrange(n):
    name, number = raw_input().split()
0
issam