[英]How do I decode unicode one line at a time in Python 2.7?
從Python 2.7加載unicode文本的正確方法如下:
content = open('filename').read().decode('encoding'):
for line in content.splitlines():
process(line)
( 更新 :不,不是。請參閱答案。)
但是,如果文件非常大,我可能希望一次讀取,解碼和處理一行,這樣整個文件永遠不會一次加載到內存中。 就像是:
for line in open('filename'):
process(line.decode('encoding'))
for
循環在打開文件句柄上的迭代是一次讀取一行的生成器。
但這不起作用,因為如果文件是utf32編碼的,那么文件中的字節(十六進制)看起來像:
hello\n = 68000000(h) 65000000(e) 6c000000(l) 6c000000(l) 6f000000(o) 0a000000(\n)
並且由for
循環分割成的行分割在\\n
字符的0a
字節上,導致(以十六進制):
lines[0] = 0x 68000000 65000000 6c000000 6c000000 6f000000 0a
lines[1] = 0x 000000
因此, \\n
字符的一部分留在第1行的末尾,其余三個字節在第2行結束(后面是第2行中的任何文本。)可以理解地在這兩行中調用decode
會導致UnicodeDecodeError
。
UnicodeDecodeError: 'utf32' codec can't decode byte 0x0a in position 24: truncated data
因此,顯然,在0a
字節上拆分unicode字節流不是將其拆分為行的正確方法。 相反,我應該分裂出現完整的四字節換行符(0x0a000000)。 但是,我認為檢測這些字符的正確方法是將字節流解碼為unicode字符串並查找\\n
字符 - 這個完整流的解碼正是我試圖避免的操作。
這不是一個不常見的要求。 處理它的正確方法是什么?
怎么樣嘗試一些像:
for line in codecs.open("filename", "rt", "utf32"):
print line
我認為這應該有效。
codecs
模塊應該為您進行翻譯。
嘗試使用編解碼器模塊:
for line in codecs.open(filename, encoding='utf32'):
do_something(line)
使用codecs.open而不是builtin open:
import codecs
for line in codecs.open('filename', encoding='encoding'):
print repr(line)
http://docs.python.org/library/codecs.html#codecs.open
當然,在完成精心設計的stackoverflow問題后,我發現了這一刻。
codecs.open
本身注意到io.open
是一個更好的選擇 (注意就在鏈接目標之上)。 它並沒有被棄用,只是因為它支持一些深奧的用法(字節 - >字節編解碼器)。
io.open
在Python 2.6及更高版本中可用 ,並提供與Py3的內置open
相同的行為,更好地優化,並且當涉及到行結束轉換之類的東西時,不會像codecs.open
那樣行為不端。 使用codecs.open
的唯一原因是你需要支持Python 2.5及更早版本,否則, io.open
會更好。
import io
# Use with statement for guaranteed, predictable cleanup
with io.open('filename', encoding='utf-32') as f:
for line in f:
process(line)
順便說一句,您可以使用io.TextIOWrapper
將任何已打開的二進制文件類對象轉換為無縫解碼基於文本的對象,因此如果其他人以二進制模式為您提供現有的類文件對象,您仍然可以隱式地逐行解碼有:
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)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.