Python'da "EOF değilken" için mükemmel muadili nedir?


115

Bazı metin dosyalarını okumak için, C veya Pascal'da, verileri EOF'ye kadar okumak için her zaman aşağıdaki parçacıkları kullanırım:

while not eof do begin
  readline(a);
  do_something;
end;

Bu yüzden Python'da bunu nasıl basit ve hızlı yapabilirim?

Yanıtlar:


192

Satırları okumak için dosya üzerinde döngü yapın:

with open('somefile') as openfileobject:
    for line in openfileobject:
        do_something()

Dosya nesneleri yinelenebilir ve EOF'ye kadar satırlar üretir. Dosya nesnesini yinelenebilir olarak kullanmak, performant okumaları sağlamak için bir arabellek kullanır.

Aynı şeyi stdin ile de yapabilirsiniz (kullanmaya gerek yoktur raw_input():

import sys

for line in sys.stdin:
    do_something()

Resmi tamamlamak için ikili okumalar şu şekilde yapılabilir:

from functools import partial

with open('somefile', 'rb') as openfileobject:
    for chunk in iter(partial(openfileobject.read, 1024), b''):
        do_something()

nerede chunkdosyasından bir defada 1024 bayt kadar tutar ve ne zaman iterasyon durur olacak openfileobject.read(1024)başlar boş bayt dizeleri dönüyor.


4
Not: lineSonunda yeni bir satır karakteri olacaktır.
ben_joseph

1
Satırları okumak, genel ikili dosyalar için biraz tehlikelidir, çünkü belki de 6GiB uzunluğunda bir hattınız vardır…
LtWorf

@LtWorf: Bu yüzden ikili dosyaların satırlar yerine yığınlar halinde nasıl okunacağını gösteriyorum .
Martijn Pieters

Devam eden bir stdinişlemden okuyorum ... bu yüzden ben süreci sonlandırana kadar EOF'ye sahip değil. Ama sonra "sonuna kadar" varıyorum ve çıkmaza giriyorum. Bunu nasıl tespit ederim ve kilitlenmeyi değil? Yeni satırlar yoksa, dosyaları okumayı bırakın (benim durumumda hiçbir zaman olmayacak bir EOF olmasa bile).
Charlie Parker

@CharlieParker: Eğer bir kilitlenmeye ulaştıysanız, muhtemelen bir şey bir arabelleği temizlemeyi unutuyordur. Gerçek bir MCVE olmadan bundan daha fazlasını söylemek zordur.
Martijn Pieters

61

Python'da C deyimini taklit edebilirsiniz.

Bayta kadar tampon okumak için şunu max_sizeyapabilirsiniz:

with open(filename, 'rb') as f:
    while True:
        buf = f.read(max_size)
        if not buf:
            break
        process(buf)

Veya satır satır bir metin dosyası:

# warning -- not idiomatic Python! See below...
with open(filename, 'rb') as f:
    while True:
        line = f.readline()
        if not line:
            break
        process(line)

Python'da bir okumadan dönen baytların eksikliği dışında eof testiwhile True / break olmadığından, yapı kullanmanız gerekir .

C'de, sahip olabilirsiniz:

while ((ch != '\n') && (ch != EOF)) {
   // read the next ch and add to a buffer
   // ..
}

Ancak, Python'da buna sahip olamazsınız:

 while (line = f.readline()):
     # syntax error

çünkü atamaları ifadelerde izin verilmez Python (Python son sürümleri bu kullanarak atama ifadeleri taklit edebilir, ancak aşağıya bakınız).

Python'da bunu yapmak kesinlikle daha deyimsel:

# THIS IS IDIOMATIC Python. Do this:
with open('somefile') as f:
    for line in f:
        process(line)

Güncelleme: Python 3.8'den beri atama ifadelerini de kullanabilirsiniz :

 while line := f.readline():
     process(line)

@MartijnPieters: Şimdi yapar :-)
dawg

3
Bir C ve Perl programcısı olarak, ifadelerde atamalara izin verilmediğine dair fikriniz benim için çok önemliydi.
KOD-REaD

1
"While True:" yöntemi, yineleme başına birden fazla girdi satırı üzerinde işlem yapmanız gerektiğinde de yararlıdır, bu deyimsel Python'un izin vermediği bir şeydir (yine de söyleyebileceğim kadarıyla).
Donald Smith

Dosya üzerinde varsayımlarda bulunmuyorsanız, satırları okumamalısınız. İkili bir dosyada çok büyük satırlar olabilir…
LtWorf

Deyimsel olmayan readline()yolun bir avantajı var gibi görünüyor : UnicodeDecodeErrordeyimsel foryinelemeyle yapamayacağınız yakalama gibi ince taneli hata işlemeyi yapabilirsiniz .
flow2k

17

Bir dosyayı açmak ve onu satır satır okumak için kullanılan Python deyimi şöyledir:

with open('filename') as f:
    for line in f:
        do_something(line)

Yukarıdaki kodun sonunda dosya otomatik olarak kapatılacaktır ( withyapı bunu halleder).

Son olarak, lineson satır satırını koruyacağını belirtmekte fayda var . Bu, aşağıdakiler kullanılarak kolayca kaldırılabilir:

line = line.rstrip()

1
1, aynı zamanda bu olduğunu OP işaret değil çok benzer aynı for line in f.readlines(): ...yaygın olarak önerilen çözüm,.
jedwards

12

Dosyanın sonuna kadar satır satır okumak için aşağıdaki kod parçacığını kullanabilirsiniz.

line = obj.readline()
while(line != ''):

    # Do Something

    line = obj.readline()

1
IMO, sorulanı en iyi yansıtan tek cevap budur.
gvrocha

Genellikle satırlar üzerinde yineleme yapmak programın yapısını bozar. Örneğin, bir dil ayrıştırıcısında satırları okumak ve sırayla işlemek istersiniz. En üst seviyeyi yeniden yapılandırmak istemezsiniz, böylece okuma satırlarını döngüye alabilir ve sonra bunları ayrıştırıcıya gönderebilirsiniz.
Jonathan Starr

11

Yukarıda "python yolu ile yapmak" için öneriler olsa da, biri gerçekten EOF'ye dayalı bir mantığa sahip olmak istiyorsa, o zaman istisna işlemeyi kullanmanın bunu yapmanın yolu olduğunu düşünüyorum -

try:
    line = raw_input()
    ... whatever needs to be done incase of no EOF ...
except EOFError:
    ... whatever needs to be done incase of EOF ...

Misal:

$ echo test | python -c "while True: print raw_input()"
test
Traceback (most recent call last):
  File "<string>", line 1, in <module> 
EOFError: EOF when reading a line

Veya Ctrl-Zbir raw_input()komut isteminde basın (Windows, Ctrl-ZLinux)


@TessellatingHeckler , dokümantasyonun söylediği şey bu değil : " Yerleşik işlevlerden biri (input () veya raw_input ()) herhangi bir veri okumadan bir dosya sonu durumuna (EOF) ulaştığında ortaya çıkar."
Tadhg McDonald-Jensen

1
@ TadhgMcDonald-Jensen Peki hey, öyle olacak. Ne kadar garip. Yanlış iddia geri çekildi ve haksız olumsuz oy kaldırıldı.
TessellatingHeckler

1

Aşağıdaki kod parçacığını kullanabilirsiniz. readlines () tüm dosyayı bir defada okur ve satıra böler.

line = obj.readlines()

0

@ Dawg'ın harika cevabına ek olarak, mors operatörünü kullanan eşdeğer çözüm (Python> = 3.8):

with open(filename, 'rb') as f:
    while buf := f.read(max_size):
        process(buf)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.