पहले से ही कई अच्छे उत्तर हैं, लेकिन अगर आपकी पूरी फ़ाइल एक ही पंक्ति में है और आप अभी भी "पंक्तियों" को संसाधित करना चाहते हैं (जैसा कि निश्चित आकार के ब्लॉक के विपरीत है), ये उत्तर आपकी मदद नहीं करेंगे।
99% समय, फाइलों की लाइन को लाइन से प्रोसेस करना संभव है। फिर, जैसा कि इस उत्तर में सुझाया गया है , आप फ़ाइल ऑब्जेक्ट को आलसी जनरेटर के रूप में उपयोग कर सकते हैं:
with open('big.csv') as f:
for line in f:
process(line)
हालांकि, मैं एक बार एक बहुत ही बहुत बड़ा (लगभग) एक पंक्ति फ़ाइल में भाग है, जहां पंक्ति विभाजक वास्तव में था नहीं '\n'
लेकिन '|'
।
- लाइन द्वारा लाइन पढ़ना एक विकल्प नहीं था, लेकिन मुझे अभी भी इसे पंक्ति द्वारा पंक्ति बनाने की आवश्यकता थी।
- प्रसंस्करण
'|'
से '\n'
पहले परिवर्तित करना भी सवाल से बाहर था, क्योंकि इस csv के कुछ क्षेत्र निहित थे'\n'
(मुक्त पाठ उपयोगकर्ता इनपुट) ।
- सीएसवी लाइब्रेरी का उपयोग करने से भी इंकार किया गया क्योंकि तथ्य यह है कि, कम से कम लिब के शुरुआती संस्करणों में, इनपुट लाइन को लाइन से पढ़ने के लिए हार्डकोड किया गया है ।
इस तरह की स्थितियों के लिए, मैंने निम्नलिखित स्निपेट बनाया:
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
मैं अपनी समस्या को हल करने के लिए इसका सफलतापूर्वक उपयोग करने में सक्षम था। यह बड़े पैमाने पर विभिन्न चंक आकारों के साथ परीक्षण किया गया है।
टेस्ट सूट, उन लोगों के लिए जो खुद को मनाना चाहते हैं।
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')
सिर्फ एक संकेतक है बिना किसी मेमोरी खपत के? (मेरा मतलब है कि खपत की गई मेमोरी फ़ाइल आकार की परवाह किए बिना समान है?) अगर मैं f.readline () के बजाय urllib.readline () का उपयोग करूं तो यह प्रदर्शन को कैसे प्रभावित करेगा?