【问题标题】:Python 2.7 "latin-1" encoding used instead of "UTF-8"使用 Python 2.7“latin-1”编码而不是“UTF-8”
【发布时间】:2016-08-19 10:29:14
【问题描述】:

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

问题 1

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

>>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”?

问题 2

虽然 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 的解决方案,那么我将非常感激 - 因为您将让我的周末免于痛苦!

提前谢谢大家!

【问题讨论】:

  • 文件系统编码总是与语言环境不同(stdout 和 stdin 编码)。请查看sys.getfilesystemencoding()
  • 您能告诉我是什么操作系统,您使用的是控制台还是 IDLE、PyCharm、Intellij 或 Eclipse 等 IDE,以便我给您具体的答案?
  • @MartijnPieters sys.getfilesystemencoding() 抛出“mbcs”
  • @AlastairMcCormack 我使用的是 Windows 7,从 PyCharm IDE 运行。
  • @kerwei:mbcs 是 Windows 支持的宽字符编码之一,它不是 UTF-8,请参阅Difference between MBCS and UTF-8 on Windows。只需使用 Python 提供的'mbcs' 编解码器即可。

标签: python-2.7 encoding utf-8 iso-8859-1 xlwt


【解决方案1】:

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

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

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

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

例如

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

注意u 前缀

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

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

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

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

例如

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

【讨论】:

  • 感谢您的解释!我正在从文件夹中读取文件,所以我真的没有选择使用带有字符串文字的 'u' 前缀。无论如何,您的回答为我指明了正确的方向,我想我现在对编码主题有了更好的理解,这要感谢link。我会将此标记为解决方案。
  • 没问题。关键是,第一次通过listdir() 传递要列出的目录时,请使用u'' 或通过其他方式创建的Unicode 对象。结果将是 Unicode。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-28
    • 1970-01-01
    • 1970-01-01
    • 2010-09-21
    • 2015-04-11
    • 1970-01-01
    • 2015-04-22
    • 1970-01-01
    相关资源
    最近更新 更多