UnicodeDecodeError发生在一个上下文中但不发生在另一个上下文中,而上下文本身似乎无关紧要。澄清?

时间:2015-07-29 02:02:42

标签: python string unicode codec utf

我有以下代码:

outlines = ""
foundnameslistlist = []
suggnameslistlist = []

filenames = []

fl = 0
flen = len(os.listdir(InputDir))
for filen in os.listdir(InputDir):
    if filen.endswith(".txt"):
        fl += 1
        foundnameslist = "\n*****************\n\n Names found--------\n"
        suggnameslist = "\n Names suggested--------\n"
        sourcefile = open(InputDir + '\\' + filen,'r')
        NLStrings = sourcefile.readlines()
        for NLS in NLStrings:
            ug = getunigrams(NLS.lower())
            nf = NField(ug, ndict, ncontextsdict, abscontextsdict)

            for fn in nf[0]:
                foundnameslist += "'" + fn[1] + "' in '" + ' '.join(fn[2]) + "'\n"
            for sn in nf[1]:
                suggnameslist += "'" + sn[1] + "' in '" + ' '.join(sn[2]) + "'\n"

        outlines += "File name: " + filen + foundnameslist + suggnameslist + "\n###################\n"

        foundnameslistlist.append(foundnameslist)
        suggnameslistlist.append(suggnameslist)

    if fl % 50 == 0:
        print(str(float(fl* 100)/flen) + "% of files completed.")

产生错误:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python27\lib\lib-tk\Tkinter.py", line 1486, in __call__
    return self.func(*args)
  File "F:\GNameHunt\NameFinderBeta.py", line 357, in ExecuteButtonClick
    NameExtract(InputButtonString.get(),OutputButtonString.get())
  File "F:\GNameHunt\NameFinderBeta.py", line 311, in NameExtract
    outlines += "File name: " + filen + foundnameslist + suggnameslist + "\n###################\n"
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 367: ordinal not in range(128)

我收到这个错误的事实告诉我,我的工作原理的心理模型是有缺陷的(即为什么它允许我创建字符串foundnameslist和suggnameslist没有任何特殊编码而没有错误然后突然当我用轮廓连接它们时失败了?显然必须有一些我不理解的东西。我也感兴趣(并且混淆)这个代码片段在另一个上下文中工作而不会产生任何错误。这里它包含在通过TKinter GUI访问的函数中,但是当我将此片段作为独立脚本的一部分运行时,即使两个实例的输入都相同,也不会发生错误。

我试过抢先将此片段中的每个字符串编码为utf-8,utf-16和utf-32,所有这些都会产生稍微不同的UnicodeDecodeError变体......甚至更糟;当我输出有问题的字符串用于调试目的时,一些字符串只包含正常的ascii字符 - 根本没有什么奇怪的,变音符号或其他。一致的是,它始终是触发错误的同一行:“轮廓+ = ......”

非常感谢您在此提供的任何见解。

编辑以澄清:使用python 2.7

编辑2:更多关注的背景

当直接从脚本调用时,名为NFind的函数本身会生成正确的输出。

sourcestring = os.getcwd() + "\\Matt Files"
NFind(sourcestring, "NameOutput.txt")

然而,相关的TKinter代码:

    def IButtonClick():
        InputButtonString.set(askdirectory())

    def OButtonClick():
        OutputButtonString.set(askopenfilename())

    def ExecuteButtonClick():
        NFind(InputButtonString.get(),OutputButtonString.get())
选择适当的输入目录和适当的输出文件后,

会产生错误。

出于好奇,我在NFind的开头放了以下两行:

print InputDir
print OutputF

在TKinter之外调用NFind(产生正确的,无错误的输出),我得到了

F:\GNameHunt\Matt Files
NameOutput.txt

在TKinter内部调用NFind(产生错误),我得到了

F:/GNameHunt/Matt Files
F:/GNameHunt/NameOutput.txt

2 个答案:

答案 0 :(得分:1)

我可以建议使用python格式化工具连接字符串而不是将它们一起添加吗?

例如:

foundnameslist += "'{0}' in '{1}'\n".format(fn[1], ' '.join(fn[2])) 

outlines += "File name: {0}{1}{2}\n###################\n".format(filen.decode('utf8'), foundnameslist.decode('utf8'), suggnameslist.decode('utf8'))

问题也可能出在您要加入的列表中。其中一个可能与其他人不相容。

如果utf8不起作用,请尝试latin1

没有看到文件的内容,很难搞清楚。

帮助您调试:

try:
    outlines += "File name: {0}{1}{2}\n###################\n".format(filen.decode('utf8'), foundnameslist.decode('utf8'), suggnameslist.decode('utf8'))
except UnicodeDecodeError as e:
    print(e)
    print(filen)
    print(foundnameslist)
    print(suggnameslist)
    continue

这将使用违规信息t打印出错误,但会继续运行

结帐pyformat - 非常有帮助

答案 1 :(得分:0)

我发现通过添加以下行:

InputDir = InputDir.encode('utf-8')
OutputF = OutputF.encode('utf-8')

在NFind功能开始时,我能够使其正常工作。遵循John Y的建议并使用print repr(x)而不是print x,我看到当通过TKinter调用NFind时,InputDir和OutputF是unicode字符串而不是默认的python字符串。 .encode(' utf-8')输出默认的字符串等价物(对我来说是违反直觉的,我认为他们会从默认转换为unicode而不是反之亦然。更多学习我将来)。

看起来文件名和目录的字符串类型可以改变这些文件的读取方式,在此之前我不会考虑这些。

感谢所有贡献者!