我在理解读取和写入文件的文本方面有一些大脑故障(Python 2.4)。

# The string, which has an a-acute in it.
ss = u'Capit\xe1n'
ss8 = ss.encode('utf8')
repr(ss), repr(ss8)

(“u’Capit \ xe1n’”、“’Capit \ xc3 \ xa1n’")

print ss, ss8
print >> open('f1','w'), ss8

>>> file('f1').read()
'Capit\xc3\xa1n\n'

于是我在我最喜欢的编辑器f2文件中输入了大写字母\xc3\xa1n。

然后:

>>> open('f1').read()
'Capit\xc3\xa1n\n'
>>> open('f2').read()
'Capit\\xc3\\xa1n\n'
>>> open('f1').read().decode('utf8')
u'Capit\xe1n\n'
>>> open('f2').read().decode('utf8')
u'Capit\\xc3\\xa1n\n'

我哪里不明白了?显然,我忽略了一些至关重要的魔力(或良好的感觉)。在文本文件中输入什么才能得到正确的转换?

我在这里真正搞不懂的是,当它来自外部时,如果你不能让Python识别它,那么UTF-8表示的意义是什么。也许我应该只是JSON转储字符串,并使用它,因为它有一个asciiable表示!更重要的是,当这个Unicode对象从文件中传入时,是否存在Python能够识别和解码的ASCII表示形式?如果有,我怎么得到它?

>>> print simplejson.dumps(ss)
'"Capit\u00e1n"'
>>> print >> file('f3','w'), simplejson.dumps(ss)
>>> simplejson.load(open('f3'))
u'Capit\xe1n'

当前回答

好吧,您最喜欢的文本编辑器没有意识到\xc3\xa1应该是字符字面量,但它将它们解释为文本。这就是为什么你在最后一行得到双反斜杠——现在在你的文件中它是一个真正的反斜杠+ xc3等等。

如果你想在Python中读写编码文件,最好使用codecs模块。

在终端和应用程序之间粘贴文本是困难的,因为您不知道哪个程序将使用哪种编码来解释您的文本。你可以试试下面的方法:

>>> s = file("f1").read()
>>> print unicode(s, "Latin-1")
Capitán

然后将这个字符串粘贴到编辑器中,并确保它使用Latin-1存储它。假设剪贴板不会使字符串乱码,那么往返应该可以工作。

其他回答

与其混淆.encode和.decode,不如在打开文件时指定编码。在Python 2.6中添加的io模块提供了一个io。Open函数,允许指定文件的编码。

假设文件用UTF-8编码,我们可以使用:

>>> import io
>>> f = io.open("test", mode="r", encoding="utf-8")

然后f.read返回一个解码后的Unicode对象:

>>> f.read()
u'Capit\xe1l\n\n'

在3。X, io。Open function是内置Open函数的别名,它支持encoding参数(在2.x中不支持)。

我们也可以使用codecs标准库模块中的open:

>>> import codecs
>>> f = codecs.open("test", "r", "utf-8")
>>> f.read()
u'Capit\xe1l\n\n'

但是请注意,当混合使用read()和readline()时,这可能会导致问题。

好吧,您最喜欢的文本编辑器没有意识到\xc3\xa1应该是字符字面量,但它将它们解释为文本。这就是为什么你在最后一行得到双反斜杠——现在在你的文件中它是一个真正的反斜杠+ xc3等等。

如果你想在Python中读写编码文件,最好使用codecs模块。

在终端和应用程序之间粘贴文本是困难的,因为您不知道哪个程序将使用哪种编码来解释您的文本。你可以试试下面的方法:

>>> s = file("f1").read()
>>> print unicode(s, "Latin-1")
Capitán

然后将这个字符串粘贴到编辑器中,并确保它使用Latin-1存储它。假设剪贴板不会使字符串乱码,那么往返应该可以工作。

所以,我找到了我想要的解决方案,那就是:

print open('f2').read().decode('string-escape').decode("utf-8")

这里有一些不寻常的编解码器很有用。这种特殊的读取允许从Python中获取UTF-8表示,将它们复制到ASCII文件中,并将它们读入Unicode。在“字符串转义”解码下,斜杠不会加倍。

这允许我想象的那种往返。

我试图用Python 2.7.9解析iCal:

从icalendar导入日历

但我得到:

 Traceback (most recent call last):
 File "ical.py", line 92, in parse
    print "{}".format(e[attr])
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe1' in position 7: ordinal not in range(128)

它只是用:

print "{}".format(e[attr].encode("utf-8"))

(现在它可以打印liké á böss。)

现在你在Python3中所需要的就是open(Filename, 'r', encoding='utf-8')

[编辑于2016-02-10,要求澄清]

Python3将encoding参数添加到其open函数中。open函数的相关信息如下:https://docs.python.org/3/library/functions.html#open

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

编码是用于解码或编码的编码的名称 文件。这应该只在文本模式中使用。默认编码为 平台相关(无论locale.getpreferredencoding()) 返回),但可以使用Python支持的任何文本编码。 有关支持的编码列表,请参阅codecs模块。

因此,通过将encoding='utf-8'作为参数添加到open函数中,文件读写都以utf8完成(这也是Python中所有操作的默认编码)。