2012-04-07 19 views
13

Tôi đang làm việc trên một công cụ Python phải có khả năng mở các tệp mã hóa UTF-8 và UTF-16. Trong Python 3.2, tôi sử dụng đoạn mã sau để thử mở các tập tin sử dụng UTF-8, sau đó thử nó với UTF-16 nếu có một lỗi unicode:Làm cách nào để mở các tệp UTF-16 trên Python 2.x?

def readGridFromPath(self, filepath): 
    try: 
     self.readGridFromFile(open(filepath,'r',encoding='utf-8')) 
    except UnicodeDecodeError: 
      self.readGridFromFile(open(filepath,'r',encoding='utf-16')) 

(readGridFromFile hoặc sẽ chạy qua để hoàn thành, hoặc huy động . một UnicodeDecodeError)

Tuy nhiên, khi tôi chạy mã này trong Python 2.x, tôi nhận được:

TypeError: 'encoding' is an invalid keyword argument for this function 

tôi thấy trong các tài liệu mà Python 2.x của open() không có một từ khóa encoding. Có cách nào xung quanh này sẽ cho phép tôi để làm cho mã của tôi Python 2.x tương thích?

Trả lời

20

io.open là mẫu thả để thay thế cho các nhu cầu của bạn, do đó, mã bạn đã cung cấp sẽ xem xét như sau bằng Python 2.x:

import io 

def readGridFromPath(self, filepath): 
    try: 
     self.readGridFromFile(io.open(filepath, 'r', encoding='utf-8')) 
    except UnicodeDecodeError: 
     self.readGridFromFile(io.open(filepath, 'r', encoding='utf-16')) 


io.open được mô tả here chi tiết. Nguyên mẫu của nó là:

io.open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True)

io module chính nó được thiết kế như lớp tương thích giữa Python 2.x và 3.x Python, để giảm bớt chuyển đổi sang Py3k và đơn giản hóa back-porting và duy trì mã Python 2.x hiện có.

Ngoài ra, xin lưu ý rằng có thể có một caveat sử dụng codecs.open, như it works in binary mode only:

Note: Files are always opened in binary mode, even if no binary mode was specified. This is done to avoid data loss due to encodings using 8-bit values. This means that no automatic conversion of '\n'` is done on reading and writing.

Ngoài ra bạn có thể chạy vào các vấn đề của tự phát hiện và tước ra UTF8 BOM - codecs.open lá UTF8 BOM inline như u'\ufeff' nhân vật .

+0

Cuộc gọi tốt, 'io.open' là tùy chọn tốt hơn. Tuy nhiên, nhược điểm của 'codecs.open' không thực sự đủ quan trọng để gọi nó là" không phù hợp ", IMHO. –

+0

Nhân tiện, tuyên bố về 'codecs.open' không xử lý BOM đúng là sai (tôi đã thử). Những điều về nó không tự động chuyển đổi dòng mới là đúng, mặc dù (nhưng điều này có vẻ là sự khác biệt duy nhất). –

+0

Tôi đã thử lại bây giờ - cho UTF-16 BE/LE nó hoạt động khá tốt, nhưng đối với UTF8, BOM (EB BB BF) của nó được để lại trong văn bản đã giải mã là u '\ ubeff'. Tôi nhớ rõ ràng tôi đã giải mã các vấn đề với BOM bằng cách sử dụng '.decode()' trên Windows, nhưng bây giờ tôi không thể kiểm tra nó. Tôi đã cố định yêu cầu đó cho sự công bằng. – toriningen

Các vấn đề liên quan