Có hai cách để mở tệp văn bản bằng Python:
f = open(filename)
Và
import codecs
f = codecs.open(filename, encoding="utf-8")
Khi nào thì codecs.open
thích hợp hơn open
?
Có hai cách để mở tệp văn bản bằng Python:
f = open(filename)
Và
import codecs
f = codecs.open(filename, encoding="utf-8")
Khi nào thì codecs.open
thích hợp hơn open
?
codecs.open()
đã lỗi thời không? Tôi không nghĩ rằng đây trong tài liệu python3: docs.python.org/3.7/library/codecs.html
Câu trả lời:
Kể từ Python 2.6, một phương pháp hay là sử dụng io.open()
, điều này cũng cần một encoding
đối số, giống như hiện đã lỗi thời codecs.open()
. Trong Python 3, io.open
là một bí danh cho tích open()
hợp sẵn. Vì vậy, io.open()
hoạt động trên Python 2.6 và tất cả các phiên bản mới hơn, bao gồm cả Python 3.4. Xem tài liệu: http://docs.python.org/3.4/library/io.html
Bây giờ, đối với câu hỏi ban đầu: khi đọc văn bản (bao gồm "văn bản thuần túy", HTML, XML và JSON) trong Python 2, bạn nên luôn sử dụng io.open()
với mã hóa rõ ràng hoặc open()
với mã hóa rõ ràng trong Python 3. Làm như vậy có nghĩa là bạn hiểu chính xác đã giải mã Unicode hoặc gặp lỗi ngay lập tức, giúp việc gỡ lỗi dễ dàng hơn nhiều.
ASCII thuần túy "văn bản thuần túy" là một huyền thoại từ quá khứ xa xôi. Văn bản tiếng Anh thích hợp sử dụng dấu ngoặc kép, dấu gạch ngang, dấu đầu dòng, € (dấu euro) và thậm chí dấu ngoặc kép (¨). Đừng ngây thơ! (Và đừng quên mẫu thiết kế Façade!)
Bởi vì ASCII thuần túy không phải là một tùy chọn thực sự, open()
không có mã hóa rõ ràng chỉ hữu ích để đọc các tệp nhị phân .
io.open()
cho văn bản và open()
chỉ cho nhị phân. Hàm ý là điều đó codecs.open()
không được ưa thích chút nào.
open
và codecs.open
, và cụ thể khi nào thì cái sau thích hợp hơn cái trước. Một câu trả lời không quá nhiều đề cập đến codecs.open
không thể trả lời câu hỏi đó.
codecs.open()
là sử dụng đúng) thì sẽ không có câu trả lời "đúng" về thời điểm sử dụng. Câu trả lời là sử dụng io.open()
thay thế. Nó giống như nếu tôi hỏi "khi nào thì nên dùng cờ lê để đóng đinh vào tường?". Câu trả lời đúng là "sử dụng một cái búa".
Cá nhân tôi luôn sử dụng codecs.open
trừ khi có nhu cầu sử dụng open
** được xác định rõ ràng . Lý do là đã rất nhiều lần tôi bị cắn khi có đầu vào utf-8 lẻn vào các chương trình của tôi. "Ồ, tôi chỉ biết nó sẽ luôn là ascii" có xu hướng là một giả định thường bị phá vỡ.
Theo kinh nghiệm của tôi, giả sử 'utf-8' làm mã hóa mặc định có xu hướng là lựa chọn mặc định an toàn hơn, vì ASCII có thể được coi là UTF-8, nhưng điều ngược lại là không đúng. Và trong những trường hợp khi tôi thực sự biết rằng đầu vào là ASCII, thì tôi vẫn làm codecs.open
như một người tin tưởng chắc chắn vào "rõ ràng tốt hơn là ẩn" .
** - trong Python 2.x, vì nhận xét về trạng thái câu hỏi trong Python 3 open
thay thếcodecs.open
open
đôi khi có thể xử lý rất tốt các nhân vật phi Latin UTF-8 mã hóa của tập unicode, và đôi khi nó không thành công miserabily ...
io.open
không mất một param mã hóa từ những gì tôi có thể nhìn thấy trong python 2.7.5
io.open
chấp nhận encoding
và newline
các tham số và giải thích chúng như Python 3. Không giống như codecs.open
, một tệp được mở bằng io.open
sẽ tăng lên TypeError: write() argument 1 must be unicode, not str
ngay cả trong Python 2.7 nếu bạn cố gắng ghi str
( bytes
) vào nó. codecs.open
Thay vào đó, một tệp được mở bằng will cố gắng chuyển đổi ngầm sang unicode
, thường dẫn đến UnicodeDecodeError
các s gây nhầm lẫn .
Trong Python 2 có các chuỗi unicode và bytestrings. Nếu bạn chỉ sử dụng bytestrings, bạn có thể đọc / ghi vào một tệp được mở open()
một cách dễ dàng. Rốt cuộc, các chuỗi chỉ là byte.
Vấn đề xảy ra khi bạn có một chuỗi unicode và bạn làm như sau:
>>> 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)
Vì vậy, ở đây rõ ràng là bạn mã hóa chuỗi unicode của mình trong utf-8 một cách rõ ràng hoặc bạn sử dụng codecs.open
để làm điều đó cho bạn một cách minh bạch.
Nếu bạn chỉ sử dụng bytestrings thì không có vấn đề gì:
>>> example = 'Μου αρέσει Ελληνικά'
>>> open('sample.txt', 'w').write(example)
>>>
Nó liên quan nhiều hơn điều này bởi vì khi bạn nối một chuỗi unicode và bytestring với +
toán tử, bạn sẽ nhận được một chuỗi unicode. Dễ bị cắn bởi con đó.
Cũng codecs.open
không thích các bytestrings với các ký tự không phải ASCII được chuyển vào:
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)
Lời khuyên về các chuỗi cho input / ouput thường là "chuyển đổi sang unicode càng sớm càng tốt và quay lại bytestrings càng muộn càng tốt". Sử dụng codecs.open
cho phép bạn làm điều sau rất dễ dàng.
Chỉ cần cẩn thận rằng bạn đang cung cấp cho nó các chuỗi unicode chứ không phải các chuỗi bytest có thể có các ký tự không phải ASCII.
u''
trong ví dụ đầu tiên. Điều này có nghĩa là tôi đã tạo một chuỗi unicode, không phải một bytestring. Đây là sự khác biệt giữa hai ví dụ. Trong ví dụ thứ hai, tôi đang tạo một bytestring và việc ghi một trong số đó vào một tệp là tốt. Một chuỗi unicode sẽ không ổn nếu bạn đang sử dụng các ký tự bên ngoài ASCII.
codecs.open
, tôi cho rằng, chỉ là phần còn lại từ những Python 2
ngày mà phần mềm mở tích hợp có giao diện đơn giản hơn nhiều và ít khả năng hơn. Trong Python 2, tích hợp sẵn open
không sử dụng đối số mã hóa, vì vậy nếu bạn muốn sử dụng thứ gì đó khác ngoài chế độ nhị phân hoặc mã hóa mặc định, thì codecs.open phải được sử dụng.
Trong đó Python 2.6
, mô-đun io đã hỗ trợ để làm cho mọi thứ đơn giản hơn một chút. Theo tài liệu chính thức
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.
Phải nói rằng, cách sử dụng duy nhất tôi có thể nghĩ đến codecs.open
trong kịch bản hiện tại là khả năng tương thích ngược. Trong tất cả các trường hợp khác (trừ khi bạn đang sử dụng Python <2,6) thì nên sử dụng io.open
. Cũng Python 3.x
io.open
giống nhưbuilt-in open
Ghi chú:
Cũng có sự khác biệt về cú pháp giữa codecs.open
và 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
và io.open
khác nhau về cú pháp, chúng trả về các đối tượng có kiểu khác nhau. Cũng codecs.open
luôn hoạt động với các tệp ở chế độ nhị phân.
Khi bạn muốn tải một tệp nhị phân, hãy sử dụng
f = io.open(filename, 'b')
.
Để mở tệp văn bản, hãy luôn sử dụng f = io.open(filename, encoding='utf-8')
mã hóa rõ ràng.
Tuy nhiên, trong python 3open
cũng làm điều tương tự io.open
và có thể được sử dụng thay thế.
Lưu ý:
codecs.open
dự kiến sẽ không còn được dùng nữa và được thay thế bằngio.open
sau khi được giới thiệu trong python 2.6 . Tôi sẽ chỉ sử dụng nó nếu mã cần tương thích với các phiên bản python trước đó. Để biết thêm thông tin về codec và unicode trong python, hãy xem Unicode HOWTO .
io.open
hoặc codecs.open
? 2. codecs.open
vẫn chưa bị phản đối, hãy đọc thảo luận trên trang bạn đã liên kết đến.
Khi bạn đang làm việc với các tệp văn bản và muốn mã hóa và giải mã trong suốt thành các đối tượng Unicode.
Tôi đã gặp phải tình huống mở tệp .asm và xử lý tệp.
#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:
Không có nhiều khó khăn, tôi có thể đọc toàn bộ tệp, bất kỳ đề xuất nào?
codecs.open()
đã lỗi thời trong 3.x, vìopen()
đạt đượcencoding
đối số.