Zaten çok sayıda iyi yanıt var, ancak dosyanızın tamamı tek bir satırdaysa ve yine de "satırları" (sabit boyutlu blokların aksine) işlemek istiyorsanız, bu cevaplar size yardımcı olmaz.
Zamanın% 99'u, dosyaları satır satır işlemek mümkündür. Daha sonra, bu cevapta önerildiği gibi , dosya nesnesinin kendisini tembel jeneratör olarak kullanabilirsiniz:
with open('big.csv') as f:
for line in f:
process(line)
Ancak, bir zamanlar satır ayırıcı aslında değil '\n'
ama çok çok büyük (neredeyse) tek satır dosyası ile karşılaştım '|'
.
- Satır satır okuma bir seçenek değildi, ama yine de satır satır işlemek gerekiyordu.
- Dönüştürme
'|'
için '\n'
bu csv alanlarının bazı içerdiği için işleme, söz konusu da önce '\n'
(serbest metin kullanıcı girişi).
- Csv kütüphanesini kullanmak da reddedildi çünkü en azından lib'in ilk sürümlerinde , girişi satır satır okumak zor .
Bu tür durumlar için aşağıdaki snippet'i oluşturdum:
def rows(f, chunksize=1024, sep='|'):
"""
Read a file where the row separator is '|' lazily.
Usage:
>>> with open('big.csv') as f:
>>> for r in rows(f):
>>> process(row)
"""
curr_row = ''
while True:
chunk = f.read(chunksize)
if chunk == '': # End of file
yield curr_row
break
while True:
i = chunk.find(sep)
if i == -1:
break
yield curr_row + chunk[:i]
curr_row = ''
chunk = chunk[i+1:]
curr_row += chunk
Sorunumu çözmek için başarıyla kullanabildim. Çeşitli yığın boyutları ile kapsamlı bir şekilde test edilmiştir.
Test paketi, kendilerini ikna etmek isteyenler için.
test_file = 'test_file'
def cleanup(func):
def wrapper(*args, **kwargs):
func(*args, **kwargs)
os.unlink(test_file)
return wrapper
@cleanup
def test_empty(chunksize=1024):
with open(test_file, 'w') as f:
f.write('')
with open(test_file) as f:
assert len(list(rows(f, chunksize=chunksize))) == 1
@cleanup
def test_1_char_2_rows(chunksize=1024):
with open(test_file, 'w') as f:
f.write('|')
with open(test_file) as f:
assert len(list(rows(f, chunksize=chunksize))) == 2
@cleanup
def test_1_char(chunksize=1024):
with open(test_file, 'w') as f:
f.write('a')
with open(test_file) as f:
assert len(list(rows(f, chunksize=chunksize))) == 1
@cleanup
def test_1025_chars_1_row(chunksize=1024):
with open(test_file, 'w') as f:
for i in range(1025):
f.write('a')
with open(test_file) as f:
assert len(list(rows(f, chunksize=chunksize))) == 1
@cleanup
def test_1024_chars_2_rows(chunksize=1024):
with open(test_file, 'w') as f:
for i in range(1023):
f.write('a')
f.write('|')
with open(test_file) as f:
assert len(list(rows(f, chunksize=chunksize))) == 2
@cleanup
def test_1025_chars_1026_rows(chunksize=1024):
with open(test_file, 'w') as f:
for i in range(1025):
f.write('|')
with open(test_file) as f:
assert len(list(rows(f, chunksize=chunksize))) == 1026
@cleanup
def test_2048_chars_2_rows(chunksize=1024):
with open(test_file, 'w') as f:
for i in range(1022):
f.write('a')
f.write('|')
f.write('a')
# -- end of 1st chunk --
for i in range(1024):
f.write('a')
# -- end of 2nd chunk
with open(test_file) as f:
assert len(list(rows(f, chunksize=chunksize))) == 2
@cleanup
def test_2049_chars_2_rows(chunksize=1024):
with open(test_file, 'w') as f:
for i in range(1022):
f.write('a')
f.write('|')
f.write('a')
# -- end of 1st chunk --
for i in range(1024):
f.write('a')
# -- end of 2nd chunk
f.write('a')
with open(test_file) as f:
assert len(list(rows(f, chunksize=chunksize))) == 2
if __name__ == '__main__':
for chunksize in [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]:
test_empty(chunksize)
test_1_char_2_rows(chunksize)
test_1_char(chunksize)
test_1025_chars_1_row(chunksize)
test_1024_chars_2_rows(chunksize)
test_1025_chars_1026_rows(chunksize)
test_2048_chars_2_rows(chunksize)
test_2049_chars_2_rows(chunksize)
f = open('really_big_file.dat')
sadece bellek tüketimi olmayan bir işaretçi mi? (Demek istediğim, kullanılan bellek dosya boyutuna bakılmaksızın aynı mı?) F.readline () yerine urllib.readline () kullanırsam performansı nasıl etkiler?