ในการอ่านไฟล์ข้อความใน C หรือ Pascal ฉันมักจะใช้ตัวอย่างต่อไปนี้เพื่ออ่านข้อมูลจนถึง EOF:
while not eof do begin
readline(a);
do_something;
end;
ดังนั้นฉันสงสัยว่าฉันจะทำสิ่งนี้ให้ง่ายและรวดเร็วใน Python ได้อย่างไร
ในการอ่านไฟล์ข้อความใน C หรือ Pascal ฉันมักจะใช้ตัวอย่างต่อไปนี้เพื่ออ่านข้อมูลจนถึง EOF:
while not eof do begin
readline(a);
do_something;
end;
ดังนั้นฉันสงสัยว่าฉันจะทำสิ่งนี้ให้ง่ายและรวดเร็วใน Python ได้อย่างไร
คำตอบ:
วนซ้ำไฟล์เพื่ออ่านบรรทัด:
with open('somefile') as openfileobject:
for line in openfileobject:
do_something()
อ็อบเจ็กต์ไฟล์สามารถทำซ้ำได้และให้ผลบรรทัดจนถึง EOF การใช้อ็อบเจ็กต์ไฟล์เป็นตัวทำซ้ำใช้บัฟเฟอร์เพื่อให้แน่ใจว่าตัวดำเนินการอ่าน
คุณสามารถทำเช่นเดียวกันกับ stdin (ไม่จำเป็นต้องใช้raw_input()
:
import sys
for line in sys.stdin:
do_something()
เพื่อให้ภาพสมบูรณ์การอ่านไบนารีสามารถทำได้ด้วย:
from functools import partial
with open('somefile', 'rb') as openfileobject:
for chunk in iter(partial(openfileobject.read, 1024), b''):
do_something()
โดยที่ไฟล์chunk
จะมีได้ถึง 1024 ไบต์ต่อครั้งและการวนซ้ำจะหยุดลงเมื่อopenfileobject.read(1024)
เริ่มส่งคืนสตริงไบต์ว่าง
stdin
จากกระบวนการทำงาน ... ดังนั้นจึงไม่มี EOF จนกว่าฉันจะฆ่ากระบวนการ แต่แล้วฉันก็มาถึง "ถึงตอนนี้" และฉันก็หยุดชะงัก ฉันจะตรวจจับสิ่งนี้และไม่หยุดชะงักได้อย่างไร เช่นถ้าไม่มีบรรทัดใหม่ให้หยุดอ่านไฟล์ (แม้ว่าจะไม่มี EOF ซึ่งในกรณีของฉันจะไม่มีอยู่)
คุณสามารถเลียนแบบ C idiom ใน Python
หากต้องการอ่านบัฟเฟอร์ถึงmax_size
จำนวนไบต์คุณสามารถทำได้:
with open(filename, 'rb') as f:
while True:
buf = f.read(max_size)
if not buf:
break
process(buf)
หรือไฟล์ข้อความทีละบรรทัด:
# warning -- not idiomatic Python! See below...
with open(filename, 'rb') as f:
while True:
line = f.readline()
if not line:
break
process(line)
คุณต้องใช้การwhile True / break
สร้างเนื่องจากไม่มีการทดสอบ eofใน Python นอกเหนือจากการขาดไบต์ที่ส่งคืนจากการอ่าน
ใน C คุณอาจมี:
while ((ch != '\n') && (ch != EOF)) {
// read the next ch and add to a buffer
// ..
}
อย่างไรก็ตามคุณไม่สามารถมีได้ใน Python:
while (line = f.readline()):
# syntax error
เนื่องจากไม่อนุญาตให้มีการมอบหมายงานในนิพจน์ใน Python (แม้ว่า Python เวอร์ชันล่าสุดสามารถเลียนแบบสิ่งนี้ได้โดยใช้นิพจน์การกำหนดดูด้านล่าง)
มันเป็นสำนวนมากกว่าใน Python ที่จะทำสิ่งนี้:
# THIS IS IDIOMATIC Python. Do this:
with open('somefile') as f:
for line in f:
process(line)
อัปเดต:เนื่องจาก Python 3.8 คุณสามารถใช้นิพจน์การกำหนดได้ :
while line := f.readline():
process(line)
readline()
คุณสามารถจัดการข้อผิดพลาดแบบละเอียดได้เช่นการจับUnicodeDecodeError
ซึ่งคุณไม่สามารถทำได้ด้วยการfor
ทำซ้ำสำนวน
สำนวน Python สำหรับเปิดไฟล์และอ่านทีละบรรทัดคือ:
with open('filename') as f:
for line in f:
do_something(line)
ไฟล์จะถูกปิดโดยอัตโนมัติในตอนท้ายของโค้ดด้านบน ( with
โครงสร้างจะดูแลสิ่งนั้น)
สุดท้ายเป็นที่น่าสังเกตว่าline
จะรักษาบรรทัดใหม่ต่อท้าย สามารถลบออกได้อย่างง่ายดายโดยใช้:
line = line.rstrip()
for line in f.readlines(): ...
โซลูชันที่คล้ายกันซึ่งเป็นวิธีการแก้ปัญหาที่แนะนำโดยทั่วไป
คุณสามารถใช้ข้อมูลโค้ดด้านล่างเพื่ออ่านทีละบรรทัดจนจบไฟล์
line = obj.readline()
while(line != ''):
# Do Something
line = obj.readline()
ในขณะที่มีคำแนะนำข้างต้นสำหรับ "ทำแบบ python" แต่ถ้าใครอยากมีตรรกะตาม EOF จริงๆฉันคิดว่าการใช้การจัดการข้อยกเว้นเป็นวิธีที่ต้องทำ -
try:
line = raw_input()
... whatever needs to be done incase of no EOF ...
except EOFError:
... whatever needs to be done incase of EOF ...
ตัวอย่าง:
$ 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
หรือกดCtrl-Zที่raw_input()
พรอมต์ (Windows, Ctrl-ZLinux)
คุณสามารถใช้ข้อมูลโค้ดต่อไปนี้ readlines () อ่านทั้งไฟล์พร้อมกันและแยกทีละบรรทัด
line = obj.readlines()
นอกเหนือจากคำตอบที่ยอดเยี่ยมของ @dawg แล้วโซลูชันที่เทียบเท่าโดยใช้ตัวดำเนินการ walrus (Python> = 3.8):
with open(filename, 'rb') as f:
while buf := f.read(max_size):
process(buf)
line
จะมีอักขระบรรทัดใหม่ต่อท้าย