มีสองวิธีในการเปิดไฟล์ข้อความใน Python:
f = open(filename)
และ
import codecs
f = codecs.open(filename, encoding="utf-8")
codecs.open
ควรเลือกเมื่อopen
ใด
มีสองวิธีในการเปิดไฟล์ข้อความใน Python:
f = open(filename)
และ
import codecs
f = codecs.open(filename, encoding="utf-8")
codecs.open
ควรเลือกเมื่อopen
ใด
คำตอบ:
ตั้งแต่ Python 2.6 การปฏิบัติที่ดีคือการใช้งานio.open()
ซึ่งยังใช้เวลาโต้แย้งเช่นล้าสมัยในขณะนี้encoding
codecs.open()
ใน Python 3 io.open
เป็นนามแฝงสำหรับไฟล์open()
. ใช้io.open()
งานได้ใน Python 2.6 และเวอร์ชันที่ใหม่กว่าทั้งหมดรวมถึง Python 3.4 ดูเอกสาร: http://docs.python.org/3.4/library/io.html
ตอนนี้สำหรับคำถามเดิม: เมื่ออ่านข้อความ (รวมทั้ง "ข้อความธรรมดา", HTML, XML และ JSON) ในหลาม 2 คุณควรเสมอใช้io.open()
กับการเข้ารหัสอย่างชัดเจนหรือopen()
มีการเข้ารหัสอย่างชัดเจนในหลาม 3. การทำเช่นนี้หมายความว่าคุณจะได้รับอย่างถูกต้อง Unicode ที่ถอดรหัสแล้วหรือได้รับข้อผิดพลาดจากแบ็ตทำให้ง่ายต่อการดีบัก
"ข้อความธรรมดา" ของ ASCII เป็นตำนานจากอดีตอันไกลโพ้น ข้อความภาษาอังกฤษที่ถูกต้องจะใช้เครื่องหมายคำพูดแบบหยิกเครื่องหมายขีดกลางสัญลักษณ์แสดงหัวข้อย่อย€ (เครื่องหมายยูโร) และแม้แต่ diaeresis (¨) อย่าไร้เดียงสา! (และอย่าลืมรูปแบบการออกแบบFaçade!)
เพราะ ASCII บริสุทธิ์ไม่ได้เป็นตัวเลือกที่แท้จริงopen()
โดยไม่ต้องมีการเข้ารหัสอย่างชัดเจนเป็นเพียงประโยชน์ในการอ่านไบนารีไฟล์
io.open()
สำหรับข้อความและopen()
สำหรับไบนารีเท่านั้น ความหมายคือcodecs.open()
ไม่ต้องการเลย
open
codecs.open
codecs.open
codecs.open()
ถูกต้องในการใช้งาน) แล้วไม่มีคำตอบที่ "ถูกต้อง" เกี่ยวกับเวลาที่จะใช้ คำตอบคือใช้io.open()
แทน มันเหมือนกับว่าฉันถามว่า "ฉันควรใช้ประแจเพื่อตอกตะปูเข้าไปในกำแพงเมื่อใด" คำตอบที่ถูกต้องคือ "ใช้ค้อน"
โดยส่วนตัวแล้วฉันมักจะใช้codecs.open
เว้นแต่จะมีการระบุไว้ชัดเจนว่าจำเป็นต้องใช้open
** เหตุผลก็คือมีหลายครั้งที่ฉันถูกกัดจากการที่อินพุต utf-8 แอบเข้าไปในโปรแกรมของฉัน "โอ้ฉันเพิ่งรู้ว่ามันจะเป็น ascii เสมอ" มักจะเป็นข้อสันนิษฐานที่พังบ่อย
สมมติว่า 'utf-8' เป็นการเข้ารหัสเริ่มต้นมีแนวโน้มที่จะเป็นตัวเลือกเริ่มต้นที่ปลอดภัยกว่าในประสบการณ์ของฉันเนื่องจาก ASCII สามารถถือเป็น UTF-8 ได้ แต่การสนทนาไม่เป็นความจริง และในกรณีดังกล่าวเมื่อผมไม่ทราบว่าเข้าเป็น ASCII แล้วฉันยังคงทำcodecs.open
ตามที่ฉันศรัทธาใน"อย่างชัดเจนจะดีกว่าโดยปริยาย"
** - ใน Python 2.x เนื่องจากความคิดเห็นของคำถามใน Python 3 open
เข้ามาแทนที่codecs.open
open
บางครั้งสามารถจัดการอักขระที่ไม่ใช่ภาษาละตินที่เข้ารหัส UTF-8 ของชุดยูนิโค้ดได้เป็นอย่างดีและบางครั้งก็ล้มเหลวอย่างไม่น่าเชื่อ ...
io.open
ไม่ใช้พารามิเตอร์การเข้ารหัสจากสิ่งที่ฉันเห็นใน python 2.7.5
io.open
ยอมรับencoding
และnewline
กำหนดพารามิเตอร์และตีความเป็น Python 3 แตกต่างจากcodecs.open
ไฟล์ที่เปิดด้วยio.open
จะเพิ่มขึ้นTypeError: write() argument 1 must be unicode, not str
แม้ใน Python 2.7 หากคุณพยายามเขียนstr
( bytes
) เข้าไป ไฟล์ที่เปิดไว้กับcodecs.open
แทนจะพยายามแปลงโดยปริยายที่จะunicode
มักจะนำไปสู่ความสับสนUnicodeDecodeError
s
ใน Python 2 มีสตริง unicode และ bytestrings หากคุณใช้ bytestrings คุณสามารถอ่าน / เขียนไปยังไฟล์ที่เปิดได้open()
อย่างดี ท้ายที่สุดสตริงเป็นเพียงไบต์
ปัญหาเกิดขึ้นเมื่อพูดว่าคุณมีสตริงยูนิโคดและคุณทำสิ่งต่อไปนี้:
>>> example = u'Μου αρέσει Ελληνικά'
>>> open('sample.txt', 'w').write(example)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)
เห็นได้ชัดว่าคุณเข้ารหัสสตริง Unicode ของคุณใน utf-8 อย่างชัดเจนหรือคุณใช้ codecs.open
ทำเพื่อคุณอย่างโปร่งใส
หากคุณเคยใช้ bytestrings เพียงอย่างเดียวก็ไม่มีปัญหา:
>>> example = 'Μου αρέσει Ελληνικά'
>>> open('sample.txt', 'w').write(example)
>>>
มันมีส่วนเกี่ยวข้องมากกว่านี้เพราะเมื่อคุณเชื่อมต่อ unicode และ bytestring string กับ+
โอเปอเรเตอร์คุณจะได้สตริง unicode ง่ายต่อการถูกกัด
ยังcodecs.open
ไม่ชอบ bytestrings ที่มีการส่งผ่านอักขระที่ไม่ใช่ ASCII:
codecs.open('test', 'w', encoding='utf-8').write('Μου αρέσει')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/codecs.py", line 691, in write
return self.writer.write(data)
File "/usr/lib/python2.7/codecs.py", line 351, in write
data, consumed = self.encode(object, self.errors)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xce in position 0: ordinal not in range(128)
คำแนะนำเกี่ยวกับสตริงสำหรับอินพุต / ouput โดยปกติคือ "แปลงเป็น Unicode ให้เร็วที่สุดและกลับไปใช้ bytestrings ให้ช้าที่สุด" การใช้codecs.open
ช่วยให้คุณทำอย่างหลังได้อย่างง่ายดาย
โปรดระวังว่าคุณกำลังให้สตริง unicode ไม่ใช่ bytestrings ที่อาจมีอักขระที่ไม่ใช่ ASCII
u''
ในตัวอย่างแรก ซึ่งหมายความว่าฉันสร้างสตริง Unicode ไม่ใช่ bytestring นี่คือความแตกต่างระหว่างสองตัวอย่าง ในตัวอย่างที่สองฉันกำลังสร้าง bytestring และเขียนหนึ่งในนั้นลงในไฟล์ก็ใช้ได้ สตริง Unicode ไม่ดีถ้าคุณใช้อักขระนอก ASCII
เมื่อคุณต้องการเปิดไฟล์ที่มีการเข้ารหัสบางอย่างคุณจะต้องใช้codecs
โมดูลนี้
codecs.open
ฉันคิดว่ามันเป็นเพียงส่วนที่เหลือจากPython 2
สมัยที่การเปิดในตัวมีอินเทอร์เฟซที่ง่ายกว่ามากและความสามารถน้อยลง ใน Python 2 บิวท์อินopen
จะไม่ใช้อาร์กิวเมนต์การเข้ารหัสดังนั้นหากคุณต้องการใช้อย่างอื่นนอกเหนือจากโหมดไบนารีหรือการเข้ารหัสเริ่มต้นควรใช้ codecs.open
ในPython 2.6
โมดูล io มีส่วนช่วยในการทำให้สิ่งต่างๆง่ายขึ้นเล็กน้อย ตามเอกสารอย่างเป็นทางการ
New in version 2.6.
The io module provides the Python interfaces to stream handling.
Under Python 2.x, this is proposed as an alternative to the
built-in file object, but in Python 3.x it is the default
interface to access files and streams.
ต้องบอกว่าสิ่งเดียวที่ฉันคิดได้codecs.open
ในสถานการณ์ปัจจุบันคือการใช้งานร่วมกันได้ ในสถานการณ์อื่น ๆ ทั้งหมด (ยกเว้นกรณีที่คุณกำลังใช้งูหลาม <2.6) io.open
มันเป็นที่นิยมในการใช้งาน นอกจากนี้ยังPython 3.x
io.open
เป็นเช่นเดียวกับbuilt-in open
บันทึก:
มีความแตกต่างทางไวยากรณ์ระหว่างcodecs.open
และio.open
เช่นกัน
codecs.open
:
open(filename, mode='rb', encoding=None, errors='strict', buffering=1)
io.open
:
open(file, mode='r', buffering=-1, encoding=None,
errors=None, newline=None, closefd=True, opener=None)
codecs.open
และio.open
แตกต่างกันในแง่ของไวยากรณ์ แต่ยังส่งคืนวัตถุประเภทต่างๆ ยังใช้codecs.open
งานได้กับไฟล์ในโหมดไบนารีเสมอ
เมื่อคุณต้องการโหลดไฟล์ไบนารีให้ใช้
f = io.open(filename, 'b')
.
สำหรับการเปิดไฟล์ข้อความให้ใช้f = io.open(filename, encoding='utf-8')
กับการเข้ารหัสที่ชัดเจนเสมอ
ในหลาม 3แต่open
จะเป็นสิ่งเดียวกันเป็นio.open
และสามารถนำมาใช้แทน
หมายเหตุ:
codecs.open
การวางแผนที่จะกลายเป็นเลิกไปและแทนที่ด้วยio.open
หลังจากที่เปิดตัวในหลาม 2.6 ฉันจะใช้มันก็ต่อเมื่อรหัสต้องเข้ากันได้กับ python เวอร์ชันก่อนหน้า สำหรับข้อมูลเพิ่มเติมเกี่ยวกับตัวแปลงสัญญาณและ Unicode ในหลามดูUnicode HOWTO
io.open
หรือcodecs.open
? 2. codecs.open
ยังไม่เลิกใช้งานโปรดอ่านการสนทนาในหน้าที่คุณเชื่อมโยงไป
เมื่อคุณทำงานกับไฟล์ข้อความและต้องการเข้ารหัสและถอดรหัสแบบโปร่งใสเป็นวัตถุ Unicode
ฉันอยู่ในสถานการณ์ที่จะเปิดไฟล์. asm และประมวลผลไฟล์
#https://docs.python.org/3/library/codecs.html#codecs.ignore_errors
#https://docs.python.org/3/library/codecs.html#codecs.Codec.encode
with codecs.open(file, encoding='cp1252', errors ='replace') as file:
ฉันสามารถอ่านไฟล์ทั้งหมดได้โดยไม่มีปัญหามีข้อเสนอแนะหรือไม่?
codecs.open()
ใน 3.x ล้าสมัยเนื่องจากopen()
ได้รับencoding
อาร์กิวเมนต์