Yanıtlar:
fileinputModülü kullanabilirsiniz :
import fileinput
for line in fileinput.input():
pass
fileinput komut satırı bağımsız değişkenlerinde verilen dosya adları olarak belirtilen girdideki tüm satırlar veya bağımsız değişken sağlanmamışsa standart girdi arasında döngü yapar.
Not: linesondaki bir yeni satır içerir; kaldırmak için kullanınline.rstrip()
Bunu yapmanın birkaç yolu var.
sys.stdinişlevleri çağırabileceğiniz readya readlinesda her şeyi okumak istiyorsanız ya da her şeyi okumak ve otomatik olarak satırsonuna göre bölmek istediğiniz dosya benzeri bir nesnedir . (Bunun import sysçalışması için gerekir .)
İsterseniz istemi kullanıcıdan giriş kullanabileceğiniz raw_inputPython 2.x ve sadece inputPython 3'te.
Sadece komut satırı seçeneklerini okumak istiyorsanız, bunlara sys.argv listesinden erişebilirsiniz .
Muhtemelen Python'daki I / O hakkındaki bu Wikibook makalesini de yararlı bir referans olarak bulacaksınız .
import sys
for line in sys.stdin:
print(line)
Bunun sonunda bir satırsonu karakteri içereceğini unutmayın. line.rstrip()Sondaki yeni satırı kaldırmak için, @brittohalloran'ın dediği gibi kullanın .
\r\nsatır sonlarıyla doğru bir şekilde ilgilenmeyecek
Python ayrıca yerleşik işlevlere sahiptir input()ve raw_input(). Yerleşik İşlevler altındaki Python belgelerine bakın .
Örneğin,
name = raw_input("Enter your name: ") # Python 2.x
veya
name = input("Enter your name: ") # Python 3
İşte Python Öğrenme'den :
import sys
data = sys.stdin.readlines()
print "Counted", len(data), "lines."
Unix'te şöyle bir şey yaparak test edebilirsiniz:
% cat countlines.py | python countlines.py
Counted 3 lines.
Windows veya DOS'ta şunları yaparsınız:
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), ''))). bkz.wc-l.py
catburada gereksiz olduğunu. Unix sistemleri için doğru çağrı python countlines.py < countlines.py.
readlines(). Dosya nesneleri, bellekteki tüm verileri gerçekleştirmeden yinelenmelidir.
Python'da stdin'den nasıl okuyorsun?
Bazı kod golf zorlukları yapmaya çalışıyorum, ama hepsi giriş stdin alınmasını gerektirir. Bunu Python'da nasıl edinebilirim?
Kullanabilirsiniz:
sys.stdin- Dosya benzeri bir nesne - sys.stdin.read()her şeyi okumak için arayın .input(prompt)- çıktı almak için isteğe bağlı bir istemi iletin, stdin'den ilk satır satırına kadar okur. Daha fazla satır elde etmek için bunu tekrar tekrar yapmanız gerekir, girişin sonunda EOFError'u yükseltir. (Muhtemelen golf için harika değil.) Python 2'de bu rawinput(prompt).open(0).read()- Python 3'te yerleşik işlev open, dosya tanımlayıcılarını (işletim sistemi IO kaynaklarını temsil eden tamsayılar) kabul eder ve 0, tanımlayıcıdır stdin. Dosya benzeri bir nesne döndürür sys.stdin- muhtemelen golf için en iyi bahistir. Python 2'de bu io.open.open('/dev/stdin').read()- open(0)Python 2 ve 3'te çalışır, ancak Windows (hatta Cygwin) üzerinde çalışmaz.fileinput.input()- listelenen tüm dosyalarda satırlar üzerinden yineleyici sys.argv[1:]veya verilmemişse stdin döndürür . Gibi kullanın ''.join(fileinput.input()).Her ikisi de sysve fileinputelbette sırasıyla ithal edilmelidir.
sys.stdinPython 2 ve 3, Windows, Unix ile uyumlu hızlı örneklerSadece gerek readdan sys.stdinsen boru veri stdin'i eğer, örneğin,:
$ echo foo | python -c "import sys; print(sys.stdin.read())"
foo
Bunun sys.stdinvarsayılan metin modunda olduğunu görebiliriz :
>>> import sys
>>> sys.stdin
<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>
Bir dosyanız inputs.txtolduğunu varsayalım, bu dosyayı kabul edebilir ve geri yazabiliriz:
python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt
İşte, iki yöntem kullanarak, yerleşik işlev input( raw_inputPython 2'de kullanın ) ve sys.stdin. Veriler değiştirilmez, bu nedenle işlem bir işlem değildir.
Başlangıç olarak, girdiler için bir dosya oluşturalım:
$ python -c "print('foo\nbar\nbaz')" > inputs.txt
Daha önce gördüğümüz kodu kullanarak dosyayı oluşturduğumuzu kontrol edebiliriz:
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt
foo
bar
baz
İşte sys.stdin.readPython 3'ten yardım :
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_inputPython 2'de)Yerleşik işlev input, standart girdiden yeni bir satıra kadar okur, bu satır (tamamlayıcı print, varsayılan olarak yeni satır ekler.) EOF (Dosya Sonu) alana kadar yükselir EOFError.
Böylece, stdin'den okumak için inputPython 3'te (veya raw_inputPython 2'de) şu şekilde kullanabilirsiniz - böylece stdindemo.py dediğimiz bir Python modülü yaratırız:
$ python -c "print('try:\n while True:\n print(input())\nexcept EOFError:\n pass')" > stdindemo.py
Ve beklediğimizden emin olmak için tekrar yazdıralım:
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < stdindemo.py
try:
while True:
print(input())
except EOFError:
pass
Yine, inputyeni satıra kadar okur ve esas olarak satırdan çıkarır. printyeni satır ekler. Böylece ikisi de girişi değiştirirken, değişiklikleri iptal edilir. (Yani aslında birbirlerinin tamamlayıcısıdırlar.)
Ve inputdosya sonu karakterini aldığında, görmezden geldiğimiz ve daha sonra programdan çıktığımız EOFError'u yükseltir.
Linux / Unix'te, kediden borulama yapabiliriz:
$ cat inputs.txt | python -m stdindemo
foo
bar
baz
Veya dosyayı stdin'den yeniden yönlendirebiliriz:
$ python -m stdindemo < inputs.txt
foo
bar
baz
Modülü komut dosyası olarak da yürütebiliriz:
$ python stdindemo.py < inputs.txt
foo
bar
baz
İşte inputPython 3'teki yerleşik yardım :
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.stdinBurada kullanarak bir demo script hazırlıyoruz sys.stdin. Dosya benzeri bir nesne üzerinde yineleme yapmanın etkili yolu, dosya benzeri nesneyi yineleyici olarak kullanmaktır. Bu girişten stdout'a yazmak için tamamlayıcı yöntem basitçe kullanmaktır sys.stdout.write:
$ python -c "print('import sys\nfor line in sys.stdin:\n sys.stdout.write(line)')" > stdindemo2.py
Doğru göründüğünden emin olmak için tekrar yazdırın:
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < stdindemo2.py
import sys
for line in sys.stdin:
sys.stdout.write(line)
Ve girdileri dosyaya yönlendirmek:
$ python -m stdindemo2 < inputs.txt
foo
bar
baz
Komuta girdi:
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt
foo
bar
baz
Dosya tanımlayıcıları için yana stdinve stdout0 ve 1 sırasıyla, biz de karşı olanlar geçebilir openPython 3 (değil 2 ve not hala Stdout'a yazma için 'w' gerektiğini) 'de.
Sisteminizde bu işe yararsa, daha fazla karakter tıraş olur.
$ python -c "open(1,'w').write(open(0).read())" < inputs.txt
baz
bar
foo
Python 2'ler io.opende bunu yapıyor, ancak içe aktarma çok daha fazla yer kaplıyor:
$ python -c "from io import open; open(1,'w').write(open(0).read())" < inputs.txt
foo
bar
baz
Bir yorum ''.join(sys.stdin)golf için önermektedir , ancak bu aslında sys.stdin.read () 'den daha uzundur - artı Python bellekte fazladan bir liste oluşturmalıdır (bir liste verilmediğinde bu şekilde str.joinçalışır) - kontrast için:
''.join(sys.stdin)
sys.stdin.read()
En iyi cevap şunları önerir:
import fileinput
for line in fileinput.input():
pass
Ancak, sys.stdinyineleyici protokolü de dahil olmak üzere dosya API'sını uyguladığından, bu sadece bununla aynıdır:
import sys
for line in sys.stdin:
pass
Başka bir cevap bunu gösteriyor. Sadece bir tercüman bunu yaparsanız, yapmanız gerektiğini unutmayın Ctrl- dLinux ya da Mac üzerinde iseniz ya Ctrl- zWindows üzerinde (sonra Entersürecine sonu dosyaya karakterini göndermek için). Ayrıca, bu cevap print(line)- '\n'sonuna sonuna bir ekleyen - kullanımını önermektedir print(line, end='')(Python 2'de ihtiyacınız varsa from __future__ import print_function).
Asıl kullanım örneği fileinputbir dizi dosyada okumak içindir.
Başkaları tarafından önerilen cevap:
for line in sys.stdin:
print line
çok basit ve pitoniktir, ancak komut satırının girdi satırlarında yinelemeye başlamadan önce EOF'a kadar bekleyeceğini belirtmek gerekir.
Bu, tail -f error_log | myscript.pysatırları beklendiği gibi işlemeyeceği anlamına gelir .
Böyle bir kullanım durumu için doğru komut dosyası şöyledir:
while 1:
try:
line = sys.stdin.readline()
except KeyboardInterrupt:
break
if not line:
break
print line
GÜNCELLEME
Yorumlardan, python 2'de yalnızca arabellekleme olabileceği temizlendi, böylece yazdırma araması yapılmadan önce arabellek veya EOF'un dolmasını beklersiniz.
for line in sys.stdin:Desen değil EOF bekleyin. Ancak çok küçük dosyalar üzerinde test yaparsanız, yanıtlar arabelleğe alınabilir. Ara sonuçları okuduğunu görmek için daha fazla veriyle test edin.
print line3.1.3 'te uyandırmaz, fakat print(line)uyanır.
for line in sys.stdin:"EOF'a kadar engellemez". Python 2'de karşılık gelen arabellek dolana kadar satırları geciktiren bir okuma hatası var . EOF ile ilgisi olmayan bir tamponlama sorunudur. Geçici çözüm için, kullanın for line in iter(sys.stdin.readline, ''):( io.open()normal dosyalar için kullanın ). Python 3'te buna ihtiyacınız yok.
Tüm anwers kullanarak sys.stdin, en az bir argüman varsa, bir argüman dosyasından okumak için aşağıdaki gibi bir şey yapabilir ve aksi takdirde stdin'e geri dönebilirsiniz:
import sys
f = open(sys.argv[1]) if len(sys.argv) > 1 else sys.stdin
for line in f:
# Do your stuff
ve ya
$ python do-my-stuff.py infile.txt
veya
$ cat infile.txt | python do-my-stuff.py
ya da
$ python do-my-stuff.py < infile.txt
Bu, Python betiğinizin cat, grepve gibi birçok GNU / Unix programı gibi davranmasını sağlar sed.
argparse kolay bir çözümdürHem Python sürüm 2 hem de 3 ile uyumlu örnek:
#!/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()
Bu komut dosyasını birçok şekilde çalıştırabilirsiniz:
1. Kullanma stdin
echo 'foo bar' | ./above-script.py
veya değiştirerek daha kısa echotarafından burada dize :
./above-script.py <<< 'foo bar'
2. Dosya adı bağımsız değişkenini kullanma
echo 'foo bar' > my-file.data
./above-script.py my-file.data
3. stdinÖzel dosya adı ile kullanma-
echo 'foo bar' | ./above-script.py -
add_argument('--in've daha sonra komut dosyasına bağlanabilir --in -ve komut satırına ekleyebilir . PS in, bir değişken / öznitelik için çok iyi bir isim değildir.
insadece bir değişken için kötü bir isim değil, yasadışı. ayrılmış anahtar kelime args.in.read()nedeniyle InvalidSyntax hatasını yükseltir in. infilePython argparse belgelerinin yaptığı gibi yeniden adlandırabilir : docs.python.org/3/library/…
Aşağıdaki kod çipi size yardımcı olacaktır (tüm stdin engellemenin EOFtek bir dizeye okunmasını sağlayacaktır ):
import sys
input_str = sys.stdin.read()
print input_str.split()
Kimse bu hack bugüne kadar bahsetmemişti oldukça şaşırdım:
python -c "import sys; set(map(sys.stdout.write,sys.stdin))"
python2'de set()aramayı bırakabilirsiniz , ancak her iki şekilde de
readlinesbölünmüş çizgileri jointekrar kullanıyorsunuz? Sadece yazabilirsinizprint(sys.stdin.read())
writegeri döner Noneve ayarlanan boyut asla 1'den büyük olmaz ( =len(set([None])))
Stdin'den okuyabilir ve daha sonra girişleri aşağıdaki gibi "veri" ye kaydedebilirsiniz :
data = ""
for line in sys.stdin:
data += line
data = sys.stdin.read()tekrarlanan dize birleştirme sorunu olmadan da yapılabilir .
Şundan okuyun sys.stdin, ancak Windows'daki ikili verileri okumak için sys.stdin, metin modunda açıldığından ve bunların \r\nyerini alması bozulacağından , çok dikkatli olmanız gerekir \n.
Çözüm, Windows + Python 2 algılanırsa ve Python 3'te kullanıldığında modu ikili olarak ayarlamaktır 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()
Aşağıdaki yöntemi kullanın, stdin (ben json ayrıştırma için kullanın) bir dize döndürür. Windows üzerinde pipe ve istem ile çalışır (henüz Linux'ta test edilmemiştir). İstendiğinde, iki satır sonu girişin sonunu gösterir.
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
Çözümde yaşadığım sorun
import sys
for line in sys.stdin:
print(line)
stdin'e herhangi bir veri iletmezseniz, sonsuza kadar engeller. Bu yüzden bu yanıtı seviyorum : önce stdin hakkında bazı veriler olup olmadığını kontrol edin ve ardından okuyun. Sonunda bunu yaptım:
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çağrı çağrıldığında giriş neredeyse hiçbir zaman "hazır" olmaz ; veya stdin yavaş bir ortamdaki (ağ, CD, kaset vb.) bir dosyaya bağlıysa sorunlarla da karşılaşabilirsiniz. "Eğer stdin'e herhangi bir veri iletmezseniz, sonsuza kadar engeller" dediniz. bir sorun , ama bir özellik olduğunu söyleyebilirim . Çoğu CLI programı (örneğin cat) bu şekilde çalışır ve beklenir. EOF, girişin sonunu algılamak için ihtiyaç duyduğunuz tek şeydir.
Bunu borulu soketleri okumak için çalışmak için alırken bazı sorunları vardı. Soket kapandığında, etkin bir döngüde boş dize döndürmeye başladı. Bu benim çözümüm (sadece linux'da test ettim, ancak umarım diğer tüm sistemlerde çalışır)
import sys, os
sep=os.linesep
while sep == os.linesep:
data = sys.stdin.readline()
sep = data[-len(os.linesep):]
print '> "%s"' % data.strip()
Dolayısıyla, bir soketi dinlemeye başlarsanız, düzgün çalışır (örneğin bash'da):
while :; do nc -l 12345 | python test.py ; done
Telnet ile arayabilir veya bir tarayıcıyı localhost'a yönlendirebilirsiniz: 12345
Bununla ilgili olarak:
for line in sys.stdin:
Sadece çok büyük bir dosya için python 2.7'de (başkasının önerisini izleyerek) denedim ve tam olarak yukarıda belirtilen nedenlerle (hiçbir şey uzun süre olmaz) önermiyorum.
Biraz daha pythonic bir çözüm buldum (ve daha büyük dosyalarda çalışır):
with open(sys.argv[1], 'r') as f:
for line in f:
Sonra betiği yerel olarak çalıştırabilirim:
python myscript.py "0 1 2 3 4..." # can be a multi-line string or filename - any std.in input will work
sys.stdin, komut dosyasına bir komut satırı argümanı olarak geçiyorum .
sys.stdinKomut dosyasına bir komut satırı argümanı olarak nasıl geçebilirsiniz ? Bağımsız değişkenler dizelerdir ve akışlar dosya benzeri nesnelerdir, aynı değildirler.
sys.stdindosya benzeri bir nesne
İçin Python 3 olacağını:
# Filename e.g. cat.py
import sys
for line in sys.stdin:
print(line, end="")
Bu temelde basit bir kedi şeklidir (1), çünkü her satırdan sonra yeni satır eklemez. Bunu kullanabilirsiniz (Dosyayı yürütülebilir chmod +x cat.pygibi işaretledikten sonra, örneğin:
echo Hello | ./cat.py
-cKomut kullanırken , zor bir yol olarak, stdin(ve bazı durumlarda daha esnek) okumak yerine , satma komutunu işaretle başlayan bir parantez içinde tırnak içine alarak bir kabuk komut dosyası komutunu da python komutunuza iletebilirsiniz $.
Örneğin
python3 -c "import sys; print(len(sys.argv[1].split('\n')))" "$(cat ~/.goldendict/history)"
Bu, goldendict'in geçmiş dosyasındaki satır sayısını sayar.