Saya mencoba melakukan beberapa tantangan kode golf , tetapi semuanya membutuhkan input untuk diambil stdin
. Bagaimana saya mendapatkannya dengan Python?
1473
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 fungsiread
ataureadlines
jika Anda ingin membaca semuanya atau Anda ingin membaca semuanya dan membaginya dengan baris baru secara otomatis. (Anda perlu agarimport sys
ini berfungsi.)Jika Anda ingin meminta input dari pengguna, Anda bisa menggunakan
raw_input
Python 2.X, dan hanyainput
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.
sumber
Perhatikan bahwa ini akan menyertakan karakter baris baru di akhir. Untuk menghapus baris baru di bagian akhir, gunakan
line.rstrip()
seperti yang dikatakan @brittohalloran.sumber
\r\n
akhiran dengan benarPython juga memiliki fungsi bawaan
input()
danraw_input()
. Lihat dokumentasi Python di bawah Fungsi Bawaan .Sebagai contoh,
atau
sumber
Ini dari Learning Python :
Di Unix, Anda dapat mengujinya dengan melakukan sesuatu seperti:
Di Windows atau DOS, Anda akan melakukan:
sumber
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 adalahpython countlines.py < countlines.py
.readlines()
. Objek file dimaksudkan untuk diulang tanpa mematerialisasi semua data dalam memori.Kamu bisa menggunakan:
sys.stdin
- Objek seperti file - panggilansys.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, inirawinput(prompt)
.open(0).read()
- Dalam Python 3, fungsi builtinopen
menerima deskriptor file (integer yang mewakili sumber daya sistem operasi IO), dan 0 adalah deskriptor daristdin
. Ini mengembalikan objek seperti filesys.stdin
- mungkin taruhan terbaik Anda untuk bermain golf. Dalam Python 2, iniio.open
.open('/dev/stdin').read()
- Mirip denganopen(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 disys.argv[1:]
, atau stdin jika tidak diberikan. Gunakan seperti''.join(fileinput.input())
.Keduanya
sys
danfileinput
harus diimpor, masing-masing, tentu saja.sys.stdin
Contoh cepat kompatibel dengan Python 2 dan 3, Windows, UnixAnda hanya perlu
read
darisys.stdin
, misalnya, jika Anda mengirim data ke stdin:Kita dapat melihat bahwa
sys.stdin
itu dalam mode teks standar:contoh file
Katakanlah Anda memiliki file,,
inputs.txt
kami dapat menerima file itu dan menulisnya kembali:Jawaban yang lebih panjang
Berikut ini adalah demo lengkap dan mudah ditiru, menggunakan dua metode, fungsi builtin,
input
(digunakanraw_input
dalam Python 2), dansys.stdin
. Data tidak dimodifikasi, sehingga pemrosesan adalah non-operasi.Untuk memulainya, mari buat file untuk input:
Dan menggunakan kode yang telah kita lihat, kita dapat memeriksa bahwa kita telah membuat file:
Ini bantuan
sys.stdin.read
dari Python 3:Fungsi bawaan,
input
(raw_input
dalam Python 2)Fungsi builtin
input
membaca dari input standar hingga baris baru, yang dilucuti (melengkapiprint
, yang menambahkan baris baru secara default.) Ini terjadi sampai mendapat EOF (End Of File), pada titik mana ia memunculkanEOFError
.Jadi, inilah cara Anda dapat menggunakan
input
Python 3 (atauraw_input
Python 2) untuk membaca dari stdin - jadi kami membuat modul Python yang kami sebut stdindemo.py:Dan mari kita cetak kembali untuk memastikannya seperti yang kita harapkan:
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:
Atau kita bisa mengarahkan file dari stdin:
Kami juga dapat menjalankan modul sebagai skrip:
Inilah bantuan pada builtin
input
dari Python 3: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 menggunakansys.stdout.write
:Cetak kembali untuk memastikan tampilannya benar:
Dan mengarahkan input ke file:
Dimasukkan ke dalam perintah:
File Deskriptor untuk Bermain Golf
Karena file deskriptor untuk
stdin
danstdout
masing-masing adalah 0 dan 1, kita juga dapat meneruskannya keopen
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 2
io.open
melakukan ini juga, tetapi impor membutuhkan lebih banyak ruang:Mengatasi komentar dan jawaban lain
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 carastr.join
kerjanya ketika tidak diberi daftar) - untuk kontras:Jawaban teratas menyarankan:
Tapi, karena
sys.stdin
mengimplementasikan file API, termasuk protokol iterator, itu sama saja dengan ini: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 - gunakanprint(line, end='')
sebagai gantinya (jika dalam Python 2, Anda akan perlufrom __future__ import print_function
).Kasus penggunaan sebenarnya
fileinput
adalah untuk membaca dalam serangkaian file.sumber
Jawaban yang diajukan oleh orang lain:
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:
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.
sumber
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, tetapiprint(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, gunakanfor line in iter(sys.stdin.readline, ''):
(gunakanio.open()
untuk file biasa). Anda tidak membutuhkannya di Python 3.Ini akan menggemakan input standar ke output standar:
sumber
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:dan gunakan itu juga
atau
atau bahkan
Itu akan membuat skrip Python Anda berperilaku seperti banyak program GNU / Unix seperti
cat
,grep
dansed
.sumber
argparse
adalah solusi mudahContoh kompatibel dengan versi Python 2 dan 3:
Anda dapat menjalankan skrip ini dengan banyak cara:
1. Menggunakan
stdin
atau lebih pendek dengan mengganti
echo
dengan sini tali :2. Menggunakan argumen nama file
3. Menggunakan
stdin
melalui nama file khusus-
sumber
add_argument('--in'
dan pipa ke skrip dan menambahkan--in -
ke baris perintah. PSin
bukan nama yang sangat bagus untuk variabel / atribut.in
bukan hanya nama buruk untuk variabel, itu ilegal.args.in.read()
akan meningkatkan kesalahan InvalidSyntax karenain
kata kunci yang dipesan. Cukup ganti nama menjadiinfile
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):sumber
Saya cukup kagum tidak ada yang menyebutkan peretasan ini sejauh ini:
di python2 Anda bisa menghentikan
set()
panggilan, tetapi akan kata baiksumber
readlines
itu dibagi menjadi beberapa baris dan sekalijoin
lagi? Anda bisa menulisprint(sys.stdin.read())
write
kembaliNone
, dan ukuran yang ditetapkan tidak akan pernah lebih besar dari 1 (=len(set([None]))
)Coba ini:
dan periksa dengan:
sumber
Anda dapat membaca dari stdin dan kemudian menyimpan input ke "data" sebagai berikut:
sumber
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, karenasys.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
.sumber
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.
sumber
Masalah yang saya miliki dengan solusi
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:
sumber
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)
Jadi, jika Anda mulai mendengarkan pada soket, itu akan berfungsi dengan baik (misalnya dalam bash):
Dan Anda dapat menyebutnya dengan telnet atau arahkan browser ke localhost: 12345
sumber
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):
Kemudian saya dapat menjalankan skrip secara lokal sebagai:
sumber
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 fileUntuk Python 3 itu adalah:
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:sumber
Ada
os.read(0, x)
yang membaca xbytes dari 0 yang mewakili stdin. Ini adalah bacaan tidak terbaca, lebih rendah daripada sys.stdin.read ()sumber
Saat menggunakan
-c
perintah, sebagai cara yang rumit, alih-alih membacastdin
(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
Ini akan menghitung jumlah baris dari file sejarah goldendict.
sumber