当他们处于列表中的最终位置时,“外国”字符丢失了

时间:2016-02-03 12:39:20

标签: python encoding

我有一个简单的Python(2.7.10)程序,如下所示:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

with open("test.txt") as f:
    input = f.readlines()

for i in input:
    l = list(i)
    mystring = ""
    for j in l:
        mystring += j
        print mystring, '\n',

文本文件'test.txt'包含:

AAAÖÖAAA

但是当我运行代码时,每次'Ö'都在mystring的末尾时,它会输出为'?',如下所示:

A 
AA 
AAA 
AAA? 
AAAÖ 
AAAÖ? 
AAAÖÖ 
AAAÖÖA 
AAAÖÖAA 
AAAÖÖAAA 
AAAÖÖAAA 

如果我在Python 3上运行代码(必须将print语句更改为 'print (mystring),'),输出正确:

A
AA
AAA
AAAÖ
AAAÖÖ
AAAÖÖA
AAAÖÖAA
AAAÖÖAAA
AAAÖÖAAA

有人知道为什么会这样,以及如何解决这个问题?我试过谷歌搜索但没有找到任何东西。

2 个答案:

答案 0 :(得分:3)

您正在打印UTF-8 bytes

UTF-8是一种可变字节编码;它将使用1到4个字节之间的任何位置来编码给定的Unicode代码点。 Ö在UTF-8中被编码为两个字节,而字母A只需要一个:

>>> u'Ö'.encode('utf8')
'\xc3\x96'
>>> u'A'.encode('utf8')
'A'

仅打印第一个字节(十六进制C3)无效UTF-8输出,因此终端使用?表示无法解码您打印的数据。在我的Mac终端上,在这种情况下打印U+FFFD REPLACEMENT CHARACTER 字符:

>>> print u'Ö'.encode('utf8')
Ö
>>> print u'Ö'.encode('utf8')[0]
�
>>> print u'Ö'.encode('utf8')[1]
�

如果您首先将数据解码为unicode对象,则可以迭代代码点而不是字节:

for i in input:
    l = list(i.decode('utf8'))

请注意,您不必在对象上调用list()进行迭代。循环一个字符串已经为你提供了单独的字符。

您也可以使用io.open()打开文件;这为您提供了一个文件对象,在阅读时默认为您提供unicode个对象,前提是您告诉它使用哪个编解码器:

import io

with io.open("test.txt", encoding='utf8') as f:
    input = f.readlines()

答案 1 :(得分:3)

解决Python 2问题的另一种方法。

而不是使用open() ...

打开文件
with open("test.txt") as f:
    input = f.readlines()

...使用io.open()

import io

with codecs.open('/tmp/b') as f:
    input = f.readlines()

io.open()与Python 3 open()内置的行为相同。