【问题标题】:Python, UTF-8 filesystem, iso-8859-1 filesPython、UTF-8 文件系统、iso-8859-1 文件
【发布时间】:2012-07-26 05:10:45
【问题描述】:

我有一个用 Python 2.7 编写的应用程序,它使用 os.walk 从硬盘读取用户文件。

应用程序需要 UTF-8 系统语言环境(我们在启动之前检查 env 变量),因为我们处理带有 Unicode 字符的文件(例如,其中包含艺术家姓名的音频文件),并希望确保我们可以保存将这些具有正确文件名的文件添加到文件系统中。

我们的一些用户使用 UTF-8 语言环境(因此是 UTF-8 fs),但仍然设法将 ISO-8859-1 文件存储在他们的驱动器上。当我们的代码尝试 os.walk() 这些目录时,这会导致问题,因为 Python 在尝试使用 UTF-8 解码此 ISO-8859-1 字节序列时会抛出异常。

所以我的问题是,我如何让 python 忽略这个文件并继续下一个文件,而不是中止 整个 os.walk()。我应该滚动自己的 os.walk() 函数吗?

编辑:到目前为止,我们一直在告诉我们的用户使用 convmv linux 命令来更正他们的文件名,但是许多用户有各种不同类型的编码(8859-1、8859-2 等),并且使用 convmv要求用户在单独对每个文件运行 convmv 之前对哪些文件具有哪些编码进行有根据的猜测。

【问题讨论】:

  • 文件名编码和终端编码有很大的不同。你永远不能假设这两者是相关的。
  • @Martijn Pieters:我们使用 LANG 环境变量。
  • 您可以使用onerror 参数到walk() 吗?抛出了什么异常?
  • @sr2222:它会抛出一个UnicodeDecodeError
  • @MartinKonecny:切换 LANG 环境变量不会切换文件系统上使用的编码; os.listdir() 使用系统上存储的文件名,这些文件名不会重新编码以适应当前的LANG 设置。

标签: python unicode utf-8 filesystems iso-8859-1


【解决方案1】:

使用字符编码检测,python 的 chardet 模块可以很好地确定实际编码,并且有一定的信心。 “酌情”——您要么知道编码,要么必须猜测它。如果使用 chardet 你猜错了,至少你试过了。

【讨论】:

    【解决方案2】:

    请阅读Unicode filenames,这是 Python Unicode 操作指南的一部分。最重要的是,文件系统编码不一定与终端中当前的 LANG 设置相同。

    具体来说,os.walk 是基于 os.listdir 构建的,因此将根据您是否给它一个 unicode 路径在 unicode 和 8 位字节之间切换。

    改为传递一个 8 位路径,您的代码将正常工作,然后根据需要从 UTF-8 或 ISO 8859-1 解码。

    【讨论】:

    • 这是要走的路。使用字节字符串(在 Python 2.x 中键入 bytesstr,在 3.x 中键入 bytes)也会使语言环境设置无关紧要。请注意,在 Python 3.2 中整个问题都已解决,因为文件名将使用 errors="surrogateescape" 解码,这永远不会失败。
    • 当前文件系统编码由环境变量LC_CTYPE决定,如果前者未设置,则由LANG决定。可以通过Python函数sys.getfilesystemencoding()查询。
    • “然后根据需要从 UTF-8 或 ISO 8859-1 解码”,我将如何处理?首先尝试从 UTF-8 解码,如果出现异常,尝试 ISO-8859-1?
    • 从 sys.getfilesystemencoding() 解码,可能使用 errors="replace" 或通过捕获 UnicodeDecode 错误并忽略相关文件名。
    猜你喜欢
    • 1970-01-01
    • 2018-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-26
    • 2011-09-21
    • 2013-05-10
    • 2010-11-18
    相关资源
    最近更新 更多