Python 3.x 带有UTF-8字符串的Python 2.7 literal_eval()

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

我正在为Python3更新一个较旧的应用程序,但如果可能的话,我会尝试保持与Python2.7的兼容性。我遇到的一个问题是,在处理UTF-8字符串时,Python 2和3之间的
ast.literal\u eval()
不一致

具体而言,我的应用程序执行的功能之一涉及:

  • 从表示Python文件名列表的UTF-8编码文本文件中读取字符串
  • 通过
    literal\u eval()
  • 使用该列表访问这些文件并执行其他处理
  • 我的test.txt文件包含以下字符串:

    ['FileName1.txt','CP1252-1-a 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上运行此测试脚本时,我得到以下结果(一切正常,如预期的那样):

    输入字符串的长度为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(no
    u
    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