2012-08-08 37 views
5

Cách đúng để tải văn bản unicode từ Python 2.7 là một cái gì đó như:Làm cách nào để giải mã unicode một dòng tại một thời điểm trong Python 2.7?

content = open('filename').read().decode('encoding'): 
for line in content.splitlines(): 
    process(line) 

(Cập nhật: Không có nó không phải là Xem câu trả lời..)

Tuy nhiên, nếu tập tin là rất lớn, tôi có thể muốn đọc, giải mã và xử lý nó một dòng tại một thời điểm, để toàn bộ tập tin không bao giờ được nạp vào bộ nhớ cùng một lúc. Một cái gì đó như:

for line in open('filename'): 
    process(line.decode('encoding'))   

Lặp lại vòng lặp qua tệp mở là bộ tạo mỗi lần đọc một dòng.

này không hoạt động mặc dù, bởi vì nếu tập tin được mã hóa utf32, ví dụ, sau đó các byte trong file (trong hex) giống như thế:

hello\n = 68000000(h) 65000000(e) 6c000000(l) 6c000000(l) 6f000000(o) 0a000000(\n) 

Và chia thành dây chuyền thực hiện bằng cách các for vòng chia trên 0a byte của nhân vật \n, kết quả (trong hex):

lines[0] = 0x 68000000 65000000 6c000000 6c000000 6f000000 0a 
lines[1] = 0x 000000 

Vì vậy, một phần của nhân vật \n còn lại ở phần cuối của dòng 1, và ba byte còn lại kết thúc trong dòng 2 (theo sau là bất kỳ văn bản nào thực sự nằm trong dòng 2.) Gọi số decode trên một trong hai dòng này có thể dễ dàng dẫn đến kết quả là UnicodeDecodeError.

UnicodeDecodeError: 'utf32' codec can't decode byte 0x0a in position 24: truncated data 

Vì vậy, rõ ràng là đủ, tách luồng byte unicode trên 0a byte không phải là cách chính xác để chia thành dòng. Thay vào đó, tôi nên chia nhỏ các lần xuất hiện của ký tự dòng mới bốn byte đầy đủ (0x0a000000). Tuy nhiên, tôi nghĩ cách chính xác để phát hiện các ký tự này là giải mã luồng byte thành chuỗi unicode và tìm kiếm các ký tự \n - và giải mã toàn bộ luồng này chính xác là hoạt động tôi đang cố tránh.

Đây không phải là yêu cầu không phổ biến. Cách chính xác để xử lý nó là gì?

+1

Bạn đã thử đọc tệp bằng phương thức codecs.open() chưa? –

+0

@Maulwurfn, tôi không biết nó tồn tại! Nhưng tôi làm bây giờ. Cảm ơn. –

Trả lời

1

codecs.open itself notes that io.open is a better option (lưu ý là ngay phía trên mục tiêu liên kết). Nó không được chấp nhận, nhưng chỉ vì nó hỗ trợ một số sử dụng bí truyền (byte-> byte codec).

io.open is available in Python 2.6 and higher và cung cấp các hành vi tương tự như tích hợp sẵn của Py3 open, được tối ưu hóa tốt hơn và không hoạt động sai như codecs.open khi nói đến nội dung như chuyển đổi kết thúc dòng. Lý do duy nhất để sử dụng codecs.open là nếu bạn cần hỗ trợ Python 2.5 trở về trước, nếu không, io.open hoàn toàn tốt hơn.

import io 

# Use with statement for guaranteed, predictable cleanup 
with io.open('filename', encoding='utf-32') as f: 
    for line in f: 
     process(line) 

Ngẫu nhiên, bạn có thể chuyển đổi bất kỳ đối tượng tập tin giống như nhị phân đã được mở đến một đối tượng văn bản giải mã liền mạch dựa using io.TextIOWrapper, vì vậy nếu ai đó cung cấp cho bạn một đối tượng tập tin giống như đang tồn tại trong chế độ nhị phân, bạn vẫn có thể thực hiện giải mã theo dòng hoàn toàn bằng:

def process_file(f): 
    if 'b' in f.mode: # Or some better test... 
     f = io.TextIOWrapper(f, encoding='utf-32') 
    for line in f: 
     process(line) 
4

Hãy thử sử dụng các module codec:

for line in codecs.open(filename, encoding='utf32'): 
    do_something(line) 
+0

Tôi đã chọn câu trả lời của @ Simon chỉ 'cos anh ấy có ít điểm hơn, nhưng có một sự nâng cao. Cảm ơn! –

+0

Huh? Bây giờ bạn chỉ có một điểm! Chuyện gì đã xảy ra!?!?! –

7

sao bạn không thử somethng như:

for line in codecs.open("filename", "rt", "utf32"): 
    print line 

Tôi nghĩ rằng điều này sẽ làm việc.

Mô-đun codecs sẽ thực hiện việc dịch cho bạn.

+0

Độc giả! Ngoài ra xem câu trả lời điểm thấp của ShadowRanger gần cuối trang này: "codecs.open tài liệu lưu ý rằng io.open là một lựa chọn tốt hơn" ... –

1

Sử dụng codecs.open thay vì BUILTIN mở:

import codecs 
for line in codecs.open('filename', encoding='encoding'): 
    print repr(line) 

http://docs.python.org/library/codecs.html#codecs.open

Tất nhiên, tôi phát hiện ra chỉ khoảnh khắc này sau khi kết thúc một cách cẩn thận crafted câu hỏi stackoverflow tôi.

+0

@jamylak, cảm ơn bạn đã sửa mã kém chất lượng của tôi. –

+0

không có vấn đề nhưng tôi chỉ cố định thụt lề :) – jamylak

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