【发布时间】:2015-10-19 19:40:53
【问题描述】:
我有以下代码:
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 而没有错误,然后突然当我将它们与轮廓连接时失败了吗?显然肯定有一些我不理解的东西)。我还感兴趣(和困惑)的是,这段代码 sn-p 确实在另一个上下文中工作而不会产生任何错误。在这里,它包含在通过 TKinter GUI 访问的函数中,但是当我将此 sn-p 作为独立脚本的一部分运行时,即使两个实例的输入相同,也不会发生错误。
我已经尝试将这个 sn-p 中的每个字符串抢先编码为 utf-8、utf-16 和 utf-32,所有这些都会产生稍微不同的 UnicodeDecodeError 变体......甚至更糟;当我让它为调试目的输出有问题的字符串时,一些字符串只包含正常的 ascii 字符——没有任何奇怪的东西,变音符号或其他。一致的事情是触发错误的总是同一行:“outlines += ...”
您可以在此处提供的任何见解将不胜感激。
编辑澄清:使用 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
【问题讨论】:
-
了解如何在每个上下文中调用此代码可能会有所帮助,因为上下文似乎是问题的根源。一旦发现差异,解决起来就会容易得多。
-
从 Tkinter 而不是从独立脚本调用时发生错误的事实确实表明问题与 Tkinter 有关。在某个地方,它需要字符串是 ASCII(最简单的 7 位编码),而它遇到的字符串不是。独立脚本显然不包含绝对需要 ASCII 的路径。
-
顺便说一句,当涉及到 Python 2 中的字符串时,不要对自己的心智模型过于苛刻。像这样难以调试的错误有助于激发字符串的设计和实现Python 3. 你需要知道的主要事情(不管你使用的是什么编程语言)是保持“字符串”(又名 Unicode)的柏拉图式理想与其实际编码表示之间的区别(通常也令人困惑称为字符串,但实际上应该称为“字节序列”)。
-
我添加了更多上下文,希望可以诊断出确切的问题。大多数时候我对 Python 2 非常满意,直到现在还没有遇到太多字符串不兼容问题。也就是说,迁移到 Python 3 听起来肯定更有吸引力。
-
感谢您添加更多信息。我不认为斜杠与反斜杠的事情应该有所作为。 Python应该能够处理它。 (如果有的话,我希望反斜杠更有可能导致问题。)您可以通过将
F:/GNameHunt/Matt Files和F:/GNameHunt/NameOutput.txt输入到非 Tkinter 调用中进行测试,看看它是否仍然有效。这应该。还有两件事:(1)在某些时候,函数显然从NameExtract更改为NFind。这可能会让阅读您的问题的人感到困惑。 (2) 调试时,用print repr(x)代替print x。
标签: python string unicode codec utf