Python 3.x 带有UTF-8字符串的Python 2.7 literal_eval()
我正在为Python3更新一个较旧的应用程序,但如果可能的话,我会尝试保持与Python2.7的兼容性。我遇到的一个问题是,在处理UTF-8字符串时,Python 2和3之间的Python 3.x 带有UTF-8字符串的Python 2.7 literal_eval(),python-3.x,python-2.7,utf-8,eval,unicode-string,Python 3.x,Python 2.7,Utf 8,Eval,Unicode String,我正在为Python3更新一个较旧的应用程序,但如果可能的话,我会尝试保持与Python2.7的兼容性。我遇到的一个问题是,在处理UTF-8字符串时,Python 2和3之间的ast.literal\u eval()不一致 具体而言,我的应用程序执行的功能之一涉及: 从表示Python文件名列表的UTF-8编码文本文件中读取字符串 通过literal\u eval() 使用该列表访问这些文件并执行其他处理 我的test.txt文件包含以下字符串: ['FileName1.txt','CP1252
ast.literal\u eval()
不一致
具体而言,我的应用程序执行的功能之一涉及:
literal\u eval()
import io
from ast import literal_eval
with io.open('z.txt','r',encoding='utf_8') as inFile:
inStr = inFile.read()
print('Input string is length '+str(len(inStr)))
fileList = literal_eval(inStr)
print(fileList)
现在,当我在Python 3上运行此测试脚本时,我得到以下结果(一切正常,如预期的那样):
输入字符串的长度为61
['FileName1.txt'、'CP1252-1-a lacrème.txt'、'dUTF8-1-??.txt']
(由于这是一个Windows CMD窗口,所以需要问号;它不处理非拉丁字符-1)
但无论如何,当我在Python 2.7上使用相同的文件运行相同的脚本时,我得到了以下结果:
输入字符串的长度为61
['FileName1.txt','CP1252-1-\xc3\xa0lacr\xc3\xa8me.txt','dUTF8-1-\xe6\x9c\xa8\xe5\x85\xb0\xe8\xbe\x9e.txt']
因此literal\u eval()
没有在结果列表中维护UTF-8编码。(或者,我猜,它试图保持编码,但它能做的最好的事情是将非ASCII数据表示为单个字节值。)
我的问题是:有没有办法让Python2
literal\u eval()
给出与Python3版本相同的结果?或者我把这当作一种限制吗?正如在评论中提到的,ast.literal\u eval
对输入的解析在Python 2和3之间是不同的。最好不要将Python源代码编写为数据文件,而是使用类似于.csv文件的模块pandas
:
如果输入是包含以下内容的UTF-8文件:
FileName1.txt,CP1252-1-àlacrème.txt,dUTF8-1-木兰辞.txt
然后,pandas
可以通过以下方式阅读:
import pandas as pd
data = pd.read_csv('test.txt',encoding='utf8',header=None)
print(data)
输出(Windows终端Python 3,需要适当的字体):
输出(Windows空闲,控制台中的Python 2需要适当的代码页才能查看表意文字):
这只是“打印”的问题吗?@GiacomoCatenazzi,不,它会影响那些列表元素的任何使用——将列表写回文件,使用元素打开引用的文件,等等。解析所有
literal\u eval
元素并将字符串转换为unicode怎么样?正如您在结果中看到的,在Python2.7(nou
prefix)@GiacomoCatenazzi上,字符串被视为字符串(而不是unicode),看起来这更接近了。我使用的不是literal\u eval()。但是现在Python 3以TypeError
异常拒绝了它(因为输入是字符串而不是类似字节的对象)。也许我只需要满足于try-except
结构,将Python-2版本作为try,将Python 3版本作为except。如果UTF-8不是默认的编解码器,例如在Windows上,此代码的工作方式也会有所不同。在Python2上,ast.literal_eval
将使用不同的默认编码将'a lacrème'
解析为字节字符串,而在Python3上它将解析为Unicode字符串。问题是将Python源语法写入文本文件。将其作为具有特定编码的CSV文件写入。Python2和Python3有不同的语法,所以ast.literal_eval是错误的工具。组合一个测试脚本,它可以在3.x和2.7上运行。谢谢
0 1 2
0 FileName1.txt CP1252-1-àlacrème.txt dUTF8-1-木兰辞.txt
0 1 2
0 FileName1.txt CP1252-1-àlacrème.txt dUTF8-1-木兰辞.txt