Python 2.7 literal_eval() 使用 UTF-8 字符串
Python 2.7 literal_eval() with a UTF-8 string
我正在为 Python 3 更新一个较旧的应用程序,但尽可能保持与 Python 2.7 的兼容性。在处理 UTF-8 字符串时,我遇到的问题之一是 Python 2 和 3 之间 ast.literal_eval()
的不一致。
具体而言,我的应用程序执行的功能之一涉及:
- 从表示 Python 文件名列表的 UTF-8 编码文本文件中读取字符串
- 通过
literal_eval()
将该 UTF-8 字符串转换为 Python 列表
- 使用该列表访问那些文件并执行其他处理。
我的测试 .txt 文件有这个字符串:
['FileName1.txt', 'CP1252-1-àlacrème.txt', 'dUTF8-1-木兰辞.txt']
我正在使用这个简短的测试脚本来模拟大型应用程序的功能:
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 上 运行 这个测试脚本时,我得到以下结果(一切正常,符合预期):
Input string is length 61
['FileName1.txt', 'CP1252-1-àlacrème.txt','dUTF8-1-???.txt']
(问号是预期的,因为这是 Windows CMD window;它不处理非 latin-1 字符)
但是无论如何,当我在 Python 2.7 上 运行 使用相同文件的相同脚本时,我得到了这个结果:
Input string is length 61
['FileName1.txt', 'CP1252-1-\xc3\xa0lacr\xc3\xa8me.txt', 'dUTF8-1-\xe6\x9c\xa8\xe5\x85\xb0\xe8\xbe\x9e.txt']
所以 literal_eval()
没有在结果列表中维护 UTF-8 编码。 (或者,我猜,正在尝试 来维护编码,但它能做的最好的事情就是将非 ASCII 数据表示为单独的字节值。)
我的问题是:有没有办法让 Python 2 literal_eval()
给出与 Python 3 版本相同的结果?还是我坚持这个限制?
如评论中所述,输入的 ast.literal_eval
在 Python 2 和 3 之间的解析不同。最好不要将 Python 源代码写为数据文件,而是使用类似的模块pandas
.csv 文件:
如果输入是 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终端Python3,需要合适的字体):
0 1 2
0 FileName1.txt CP1252-1-àlacrème.txt dUTF8-1-木兰辞.txt
输出(Windows IDLE,Python 2 在控制台中需要适当的代码页来查看表意文字):
0 1 2
0 FileName1.txt CP1252-1-àlacrème.txt dUTF8-1-木兰辞.txt
我正在为 Python 3 更新一个较旧的应用程序,但尽可能保持与 Python 2.7 的兼容性。在处理 UTF-8 字符串时,我遇到的问题之一是 Python 2 和 3 之间 ast.literal_eval()
的不一致。
具体而言,我的应用程序执行的功能之一涉及:
- 从表示 Python 文件名列表的 UTF-8 编码文本文件中读取字符串
- 通过
literal_eval()
将该 UTF-8 字符串转换为 Python 列表
- 使用该列表访问那些文件并执行其他处理。
我的测试 .txt 文件有这个字符串:
['FileName1.txt', 'CP1252-1-àlacrème.txt', 'dUTF8-1-木兰辞.txt']
我正在使用这个简短的测试脚本来模拟大型应用程序的功能:
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 上 运行 这个测试脚本时,我得到以下结果(一切正常,符合预期):
Input string is length 61
['FileName1.txt', 'CP1252-1-àlacrème.txt','dUTF8-1-???.txt']
(问号是预期的,因为这是 Windows CMD window;它不处理非 latin-1 字符)
但是无论如何,当我在 Python 2.7 上 运行 使用相同文件的相同脚本时,我得到了这个结果:
Input string is length 61
['FileName1.txt', 'CP1252-1-\xc3\xa0lacr\xc3\xa8me.txt', 'dUTF8-1-\xe6\x9c\xa8\xe5\x85\xb0\xe8\xbe\x9e.txt']
所以 literal_eval()
没有在结果列表中维护 UTF-8 编码。 (或者,我猜,正在尝试 来维护编码,但它能做的最好的事情就是将非 ASCII 数据表示为单独的字节值。)
我的问题是:有没有办法让 Python 2 literal_eval()
给出与 Python 3 版本相同的结果?还是我坚持这个限制?
如评论中所述,输入的 ast.literal_eval
在 Python 2 和 3 之间的解析不同。最好不要将 Python 源代码写为数据文件,而是使用类似的模块pandas
.csv 文件:
如果输入是 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终端Python3,需要合适的字体):
0 1 2
0 FileName1.txt CP1252-1-àlacrème.txt dUTF8-1-木兰辞.txt
输出(Windows IDLE,Python 2 在控制台中需要适当的代码页来查看表意文字):
0 1 2
0 FileName1.txt CP1252-1-àlacrème.txt dUTF8-1-木兰辞.txt