Jawaban:
Anda bisa menggunakan fileinput
modul:
import fileinput
for line in fileinput.input():
pass
fileinput
akan mengulangi semua baris dalam input yang ditentukan sebagai nama file yang diberikan dalam argumen baris perintah, atau input standar jika tidak ada argumen yang diberikan.
Catatan: line
akan berisi baris tambahan tambahan; untuk menghapusnya gunakanline.rstrip()
Ada beberapa cara untuk melakukannya.
sys.stdin
adalah objek seperti file tempat Anda dapat memanggil fungsi read
atau readlines
jika Anda ingin membaca semuanya atau Anda ingin membaca semuanya dan membaginya dengan baris baru secara otomatis. (Anda perlu agar import sys
ini berfungsi.)
Jika Anda ingin meminta input dari pengguna, Anda bisa menggunakan raw_input
Python 2.X, dan hanya input
di Python 3.
Jika Anda sebenarnya hanya ingin membaca opsi baris perintah, Anda dapat mengaksesnya melalui daftar sys.argv .
Anda mungkin akan menemukan artikel Wikibook ini di I / O dengan Python sebagai referensi yang berguna juga.
import sys
for line in sys.stdin:
print(line)
Perhatikan bahwa ini akan menyertakan karakter baris baru di akhir. Untuk menghapus baris baru di bagian akhir, gunakan line.rstrip()
seperti yang dikatakan @brittohalloran.
\r\n
akhiran dengan benar
Python juga memiliki fungsi bawaan input()
dan raw_input()
. Lihat dokumentasi Python di bawah Fungsi Bawaan .
Sebagai contoh,
name = raw_input("Enter your name: ") # Python 2.x
atau
name = input("Enter your name: ") # Python 3
Ini dari Learning Python :
import sys
data = sys.stdin.readlines()
print "Counted", len(data), "lines."
Di Unix, Anda dapat mengujinya dengan melakukan sesuatu seperti:
% cat countlines.py | python countlines.py
Counted 3 lines.
Di Windows atau DOS, Anda akan melakukan:
C:\> type countlines.py | python countlines.py
Counted 3 lines.
print(sum(chunk.count('\n') for chunk in iter(partial(sys.stdin.read, 1 << 15), '')))
. lihatwc-l.py
cat
sini berlebihan. Doa yang benar untuk sistem Unix adalah python countlines.py < countlines.py
.
readlines()
. Objek file dimaksudkan untuk diulang tanpa mematerialisasi semua data dalam memori.
Bagaimana Anda membaca dari stdin dengan Python?
Saya mencoba melakukan beberapa tantangan kode golf, tetapi mereka semua membutuhkan input yang akan diambil dari stdin. Bagaimana saya mendapatkannya dengan Python?
Kamu bisa menggunakan:
sys.stdin
- Objek seperti file - panggilan sys.stdin.read()
untuk membaca semuanya.input(prompt)
- berikan prompt opsional untuk output, ia membaca dari stdin hingga baris baru pertama, yang dilucuti. Anda harus melakukan ini berulang kali untuk mendapatkan lebih banyak baris, pada akhir input yang memunculkan EOFError. (Mungkin tidak bagus untuk bermain golf.) Dalam Python 2, ini rawinput(prompt)
.open(0).read()
- Dalam Python 3, fungsi builtin open
menerima deskriptor file (integer yang mewakili sumber daya sistem operasi IO), dan 0 adalah deskriptor dari stdin
. Ini mengembalikan objek seperti file sys.stdin
- mungkin taruhan terbaik Anda untuk bermain golf. Dalam Python 2, ini io.open
.open('/dev/stdin').read()
- Mirip dengan open(0)
, bekerja pada Python 2 dan 3, tetapi tidak pada Windows (atau bahkan Cygwin).fileinput.input()
- Mengembalikan iterator melalui baris di semua file yang terdaftar di sys.argv[1:]
, atau stdin jika tidak diberikan. Gunakan seperti ''.join(fileinput.input())
.Keduanya sys
dan fileinput
harus diimpor, masing-masing, tentu saja.
sys.stdin
Contoh cepat kompatibel dengan Python 2 dan 3, Windows, UnixAnda hanya perlu read
dari sys.stdin
, misalnya, jika Anda mengirim data ke stdin:
$ echo foo | python -c "import sys; print(sys.stdin.read())"
foo
Kita dapat melihat bahwa sys.stdin
itu dalam mode teks standar:
>>> import sys
>>> sys.stdin
<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>
Katakanlah Anda memiliki file,, inputs.txt
kami dapat menerima file itu dan menulisnya kembali:
python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt
Berikut ini adalah demo lengkap dan mudah ditiru, menggunakan dua metode, fungsi builtin, input
(digunakan raw_input
dalam Python 2), dan sys.stdin
. Data tidak dimodifikasi, sehingga pemrosesan adalah non-operasi.
Untuk memulainya, mari buat file untuk input:
$ python -c "print('foo\nbar\nbaz')" > inputs.txt
Dan menggunakan kode yang telah kita lihat, kita dapat memeriksa bahwa kita telah membuat file:
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt
foo
bar
baz
Ini bantuan sys.stdin.read
dari Python 3:
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
( raw_input
dalam Python 2)Fungsi builtin input
membaca dari input standar hingga baris baru, yang dilucuti (melengkapi print
, yang menambahkan baris baru secara default.) Ini terjadi sampai mendapat EOF (End Of File), pada titik mana ia memunculkan EOFError
.
Jadi, inilah cara Anda dapat menggunakan input
Python 3 (atau raw_input
Python 2) untuk membaca dari stdin - jadi kami membuat modul Python yang kami sebut stdindemo.py:
$ python -c "print('try:\n while True:\n print(input())\nexcept EOFError:\n pass')" > stdindemo.py
Dan mari kita cetak kembali untuk memastikannya seperti yang kita harapkan:
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < stdindemo.py
try:
while True:
print(input())
except EOFError:
pass
Sekali lagi, input
baca sampai baris baru dan pada dasarnya menghapusnya dari baris. print
menambahkan baris baru. Jadi sementara mereka berdua memodifikasi input, modifikasi mereka dibatalkan. (Jadi mereka pada dasarnya saling melengkapi.)
Dan ketika input
mendapatkan karakter end-of-file, itu menimbulkan EOFError, yang kita abaikan dan kemudian keluar dari program.
Dan di Linux / Unix, kita dapat melakukan pipe dari cat:
$ cat inputs.txt | python -m stdindemo
foo
bar
baz
Atau kita bisa mengarahkan file dari stdin:
$ python -m stdindemo < inputs.txt
foo
bar
baz
Kami juga dapat menjalankan modul sebagai skrip:
$ python stdindemo.py < inputs.txt
foo
bar
baz
Inilah bantuan pada builtin input
dari Python 3:
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
Di sini kami membuat skrip demo menggunakan sys.stdin
. Cara efisien untuk beralih pada objek seperti file adalah dengan menggunakan objek seperti file sebagai iterator. Metode komplementer untuk menulis ke stdout dari input ini adalah dengan menggunakan sys.stdout.write
:
$ python -c "print('import sys\nfor line in sys.stdin:\n sys.stdout.write(line)')" > stdindemo2.py
Cetak kembali untuk memastikan tampilannya benar:
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < stdindemo2.py
import sys
for line in sys.stdin:
sys.stdout.write(line)
Dan mengarahkan input ke file:
$ python -m stdindemo2 < inputs.txt
foo
bar
baz
Dimasukkan ke dalam perintah:
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt
foo
bar
baz
Karena file deskriptor untuk stdin
dan stdout
masing-masing adalah 0 dan 1, kita juga dapat meneruskannya ke open
dalam Python 3 (bukan 2, dan perhatikan bahwa kita masih membutuhkan 'w' untuk menulis ke stdout).
Jika ini bekerja pada sistem Anda, itu akan memangkas lebih banyak karakter.
$ python -c "open(1,'w').write(open(0).read())" < inputs.txt
baz
bar
foo
Python 2 io.open
melakukan ini juga, tetapi impor membutuhkan lebih banyak ruang:
$ python -c "from io import open; open(1,'w').write(open(0).read())" < inputs.txt
foo
bar
baz
Satu komentar menyarankan ''.join(sys.stdin)
untuk bermain golf tapi itu sebenarnya lebih lama dari sys.stdin.read () - ditambah Python harus membuat daftar tambahan di memori (itulah cara str.join
kerjanya ketika tidak diberi daftar) - untuk kontras:
''.join(sys.stdin)
sys.stdin.read()
Jawaban teratas menyarankan:
import fileinput
for line in fileinput.input():
pass
Tapi, karena sys.stdin
mengimplementasikan file API, termasuk protokol iterator, itu sama saja dengan ini:
import sys
for line in sys.stdin:
pass
Jawaban lain tidak menyarankan ini. Ingatlah bahwa jika Anda melakukannya dalam juru bahasa, Anda harus melakukan Ctrl- djika Anda menggunakan Linux atau Mac, atau Ctrl- zpada Windows (setelah Enter) untuk mengirim karakter akhir file ke proses. Juga, jawaban itu menyarankan print(line)
- yang menambahkan a '\n'
ke akhir - gunakan print(line, end='')
sebagai gantinya (jika dalam Python 2, Anda akan perlu from __future__ import print_function
).
Kasus penggunaan sebenarnya fileinput
adalah untuk membaca dalam serangkaian file.
Jawaban yang diajukan oleh orang lain:
for line in sys.stdin:
print line
sangat sederhana dan pythonic, tetapi harus dicatat bahwa skrip akan menunggu sampai EOF sebelum mulai beralih pada baris input.
Ini berarti bahwa tail -f error_log | myscript.py
tidak akan memproses garis seperti yang diharapkan.
Skrip yang benar untuk kasus penggunaan seperti itu adalah:
while 1:
try:
line = sys.stdin.readline()
except KeyboardInterrupt:
break
if not line:
break
print line
MEMPERBARUI
Dari komentar telah dihapus bahwa pada python 2 hanya mungkin ada buffering yang terlibat, sehingga Anda akhirnya menunggu buffer untuk mengisi atau EOF sebelum panggilan cetak dikeluarkan.
for line in sys.stdin:
Pola tidak menunggu EOF. Tetapi jika Anda menguji pada file yang sangat kecil, respons mungkin mendapat buffered. Uji dengan lebih banyak data untuk melihat bahwa itu membaca hasil antara.
print line
tidak terbangun pada 3.1.3, tetapi print(line)
tidak.
for line in sys.stdin:
tidak "memblokir sampai EOF". Ada bug baca-depan di Python 2 yang menunda baris sampai buffer yang sesuai penuh. Ini adalah masalah buffering yang tidak terkait dengan EOF. Untuk mengatasinya, gunakan for line in iter(sys.stdin.readline, ''):
(gunakan io.open()
untuk file biasa). Anda tidak membutuhkannya di Python 3.
Membangun semua jawaban menggunakan sys.stdin
, Anda juga dapat melakukan sesuatu seperti berikut untuk membaca dari file argumen jika setidaknya ada satu argumen, dan kembali ke stdin sebaliknya:
import sys
f = open(sys.argv[1]) if len(sys.argv) > 1 else sys.stdin
for line in f:
# Do your stuff
dan gunakan itu juga
$ python do-my-stuff.py infile.txt
atau
$ cat infile.txt | python do-my-stuff.py
atau bahkan
$ python do-my-stuff.py < infile.txt
Itu akan membuat skrip Python Anda berperilaku seperti banyak program GNU / Unix seperti cat
, grep
dansed
.
argparse
adalah solusi mudahContoh kompatibel dengan versi Python 2 dan 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()
Anda dapat menjalankan skrip ini dengan banyak cara:
1. Menggunakan stdin
echo 'foo bar' | ./above-script.py
atau lebih pendek dengan mengganti echo
dengan sini tali :
./above-script.py <<< 'foo bar'
2. Menggunakan argumen nama file
echo 'foo bar' > my-file.data
./above-script.py my-file.data
3. Menggunakan stdin
melalui nama file khusus-
echo 'foo bar' | ./above-script.py -
add_argument('--in'
dan pipa ke skrip dan menambahkan --in -
ke baris perintah. PS in
bukan nama yang sangat bagus untuk variabel / atribut.
in
bukan hanya nama buruk untuk variabel, itu ilegal. args.in.read()
akan meningkatkan kesalahan InvalidSyntax karena in
kata kunci yang dipesan. Cukup ganti nama menjadi infile
seperti python argparse docs lakukan: docs.python.org/3/library/…
Chip kode berikut akan membantu Anda (ini akan membaca semua stdin yang menghalangi EOF
, menjadi satu string):
import sys
input_str = sys.stdin.read()
print input_str.split()
Saya cukup kagum tidak ada yang menyebutkan peretasan ini sejauh ini:
python -c "import sys; set(map(sys.stdout.write,sys.stdin))"
di python2 Anda bisa menghentikan set()
panggilan, tetapi akan kata baik
readlines
itu dibagi menjadi beberapa baris dan sekali join
lagi? Anda bisa menulisprint(sys.stdin.read())
write
kembali None
, dan ukuran yang ditetapkan tidak akan pernah lebih besar dari 1 ( =len(set([None]))
)
Anda dapat membaca dari stdin dan kemudian menyimpan input ke "data" sebagai berikut:
data = ""
for line in sys.stdin:
data += line
data = sys.stdin.read()
, tanpa masalah penggabungan string berulang.
Baca dari sys.stdin
, tetapi untuk membaca data biner pada Windows , Anda harus ekstra hati-hati, karena sys.stdin
ada yang dibuka dalam mode teks dan akan rusak \r\n
menggantinya dengan\n
.
Solusinya adalah mengatur mode ke biner jika Windows + Python 2 terdeteksi, dan menggunakan 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()
Saya menggunakan metode berikut, ia mengembalikan string dari stdin (saya menggunakannya untuk parsing json). Ini bekerja dengan pipa dan meminta pada Windows (belum diuji di Linux). Saat diminta, dua jeda baris menunjukkan akhir input.
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
Masalah yang saya miliki dengan solusi
import sys
for line in sys.stdin:
print(line)
adalah bahwa jika Anda tidak meneruskan data apa pun ke stdin, itu akan diblokir selamanya. Itu sebabnya saya suka jawaban ini : periksa apakah ada beberapa data tentang stdin pertama, dan kemudian bacalah. Inilah yang akhirnya saya lakukan:
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)
select
dipanggil; atau Anda juga bisa menghadapi masalah jika stdin terhubung ke file pada media yang lambat (jaringan, CD, tape, dll.). Anda mengatakan bahwa "jika Anda tidak meneruskan data apa pun ke stdin, itu akan diblokir selamanya." adalah masalah , tapi saya akan mengatakan itu fitur . Sebagian besar program CLI (mis. cat
) Bekerja dengan cara ini, dan mereka diharapkan untuk melakukannya. EOF adalah satu-satunya hal yang harus Anda andalkan untuk mendeteksi akhir input.
Saya memiliki beberapa masalah ketika membuat ini berfungsi untuk membaca soket yang disalurkan ke sana. Ketika soket ditutup, ia mulai mengembalikan string kosong dalam loop aktif. Jadi ini solusi saya untuk itu (yang hanya saya uji di linux, tapi saya harap ini berhasil di semua sistem lain)
import sys, os
sep=os.linesep
while sep == os.linesep:
data = sys.stdin.readline()
sep = data[-len(os.linesep):]
print '> "%s"' % data.strip()
Jadi, jika Anda mulai mendengarkan pada soket, itu akan berfungsi dengan baik (misalnya dalam bash):
while :; do nc -l 12345 | python test.py ; done
Dan Anda dapat menyebutnya dengan telnet atau arahkan browser ke localhost: 12345
Mengenai hal ini:
for line in sys.stdin:
Saya baru mencobanya di python 2.7 (mengikuti saran orang lain) untuk file yang sangat besar, dan saya tidak merekomendasikannya, justru karena alasan yang disebutkan di atas (tidak ada yang terjadi untuk waktu yang lama).
Saya berakhir dengan solusi pythonic yang sedikit lebih (dan ini bekerja pada file yang lebih besar):
with open(sys.argv[1], 'r') as f:
for line in f:
Kemudian saya dapat menjalankan skrip secara lokal sebagai:
python myscript.py "0 1 2 3 4..." # can be a multi-line string or filename - any std.in input will work
sys.stdin
sebagai argumen baris perintah untuk skrip.
sys.stdin
sebagai argumen baris perintah ke skrip? Argumen adalah string dan stream adalah objek seperti file, mereka tidak sama.
sys.stdin
adalah objek seperti file
Untuk Python 3 itu adalah:
# Filename e.g. cat.py
import sys
for line in sys.stdin:
print(line, end="")
Ini pada dasarnya adalah bentuk sederhana kucing (1), karena tidak menambahkan baris baru setelah setiap baris. Anda dapat menggunakan ini (setelah Anda menandai file yang dapat dieksekusi menggunakan chmod +x cat.py
seperti:
echo Hello | ./cat.py
Saat menggunakan -c
perintah, sebagai cara yang rumit, alih-alih membaca stdin
(dan lebih fleksibel dalam beberapa kasus), Anda dapat meneruskan perintah skrip shell juga ke perintah python Anda dengan memasukkan perintah jual dalam tanda kutip di dalam tanda kurung yang dimulai oleh$
tanda.
misalnya
python3 -c "import sys; print(len(sys.argv[1].split('\n')))" "$(cat ~/.goldendict/history)"
Ini akan menghitung jumlah baris dari file sejarah goldendict.