Python 2.7 使用 "latin-1" 编码代替 "UTF-8"

Python 2.7 "latin-1" encoding used instead of "UTF-8"

我知道在 Python 2 上有很多关于 "UTF-8" 编码问题的讨论,但到目前为止我找不到解决问题的方法。我目前正在创建一个脚本来获取文件名并将其超链接到 xlwt 中,以便可以通过在电子表格中单击来访问该文件。问题是,这些文件的某些名称包含非 ASCII 字符。

问题一

我使用以下行来检索文件名。顺便说下文件夹里只有一个文件

>>f = filter(os.path.isfile, os.listdir(tmp_path))[0]

然后

>>print f
'521001ldrAvisoAcionistas(Retifica\xe7\xe3o)_doc'
>>print sys.stdout.encoding
'UTF-8'
>>f.decode("UTF-8")
*** UnicodeDecodeError: 'utf8' codec can't decode byte 0xe7 in position 76: invalid continuation byte

通过浏览此处的讨论,我意识到“\xe7\xe3o”不是 "UTF-8" 编码。 运行 下面这行似乎支持了这一点。

>>f.decode("latin-1")
u'521001ldrAvisoAcionistas(Retifica\xe7\xe3o)_doc'

那么我的问题是,为什么系统编码设置为"UTF-8"时变量f被编码为"latin-1"?

问题二

虽然 f.decode("latin-1") 给出了我想要的输出,但我仍然无法将变量提供给电子表格中的超链接函数。

 >>data.append(["File", xlwt.Formula('HYPERLINK("%s";"%s")' % (os.path.join(dl_path,f.decode("latin-1")),f.decode("latin-1")))])
*** FormulaParseException: can't parse formula HYPERLINK("u'H:\Mad Lab\SE Doc Crawler\bovespa\download\521001ldrAvisoAcionistas(Retifica\xe7\xe3o)_doc's;"u'521001ldrAvisoAcionistas(Retifica\xe7\xe3o)_doc's)

显然,右双引号被吃掉了,取而代之的是“'s”后缀。有人可以帮忙解释一下这里发生了什么吗? 0.0

哦,如果有人可以为上面的问题 2 提出解决方案,那么我将非常感激 - 因为你会让我的周末免于痛苦!

在此先感谢大家!

欢迎来到令人困惑的编码世界!至少要处理文件编码、终端编码和文件名编码,这三者可能不同。

在Python2.x中,目标是从一个编码的字符串中得到一个Unicode字符串(不同于str)。问题是您并不总是知道用于 str 的编码,因此很难对其进行解码。

当使用 listdir() 获取文件名时,有一个已记录但经常被忽视的怪癖 - 如果您将 str 传递给 listdir(),您将得到 str 的编码。这些将根据您的语言环境进行编码。在 Windows 上,这些将是一个 8 位字符集,如 windows-1252

或者,传递 listdir() Unicode 字符串。

例如

os.listdir(u'C:\mydir')

注意 u 前缀

这将return 正确解码 Unicode 文件名。在 Windows 和 OS X 上,只要您的环境语言环境没有被弄乱,这是非常可靠的。

在你的情况下,listdir() 会 return:

u'521001ldrAvisoAcionistas(Retifica\xe7\xe3o)_doc'

再次注意 u 前缀。您现在可以将其打印到您的 PyCharm 控制台,无需修改。

例如

f = filter(os.path.isfile, os.listdir(tmp_path))[0]
print f

至于问题 2,由于时间限制,我没有进一步调查,只是将输出打印为 unicode 字符串,而不是 xlwt 对象。我能够继续这个项目,尽管不了解这里出了什么问题。从这个意义上说,上面的两个问题已经得到了回答。