มีสองวิธีในการเปิดไฟล์ข้อความใน 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()ไม่ต้องการเลย
opencodecs.opencodecs.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มักจะนำไปสู่ความสับสนUnicodeDecodeErrors
ใน 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อาร์กิวเมนต์