【问题标题】:Python's os.path choking on Hebrew filenamesPython os.path 窒息希伯来文文件名
【发布时间】:2010-10-04 13:51:36
【问题描述】:

我正在编写一个必须移动一些文件的脚本,但不幸的是,os.path 似乎不太适合国际化。当我有以希伯来语命名的文件时,就会出现问题。这是目录内容的屏幕截图:


(来源:thegreenplace.net

现在考虑遍历此目录中文件的这段代码:

files = os.listdir('test_source')

for f in files:
    pf = os.path.join('test_source', f)
    print pf, os.path.exists(pf)

输出是:

test_source\ex True
test_source\joe True
test_source\mie.txt True
test_source\__()'''.txt True
test_source\????.txt False

注意os.path.exists 是如何认为希伯来文命名的文件甚至不存在的? 我该如何解决这个问题?

Windows XP Home SP2 上的 ActivePython 2.5.2

【问题讨论】:

    标签: python internationalization hebrew


    【解决方案1】:

    这看起来像是一个 Unicode 与 ASCII 问题 - os.listdir 正在返回一个 ASCII 字符串列表。

    编辑:我在 Python 3.0 和 XP SP2 上都试过了,os.listdir 只是省略了希伯来文文件名,根本没有列出它们。

    根据文档,这意味着它无法解码:

    注意当 os.listdir() 返回一个 字符串列表,不能的文件名 被正确解码而被省略 而不是引发 UnicodeError。

    【讨论】:

    • 我想我可以尝试,但这对我没有帮助,因为我目前无法迁移到 3.0。我确定应该有 2.5 的解决方案
    【解决方案2】:

    在 OS X 上使用 Python 2.5.1 就像一个魅力:

    subdir/bar.txt True
    subdir/foo.txt True
    subdir/עִבְרִית.txt True
    

    也许这意味着这与 Windows XP 有某种关系?

    编辑:我还尝试使用 unicode 字符串来更好地模仿 Windows 行为:

    for f in os.listdir(u'subdir'):
      pf = os.path.join(u'subdir', f)
      print pf, os.path.exists(pf)
    
    subdir/bar.txt True
    subdir/foo.txt True
    subdir/עִבְרִית.txt True
    

    在终端(os x stock command prompt app)中。使用 IDLE 它仍然有效,但没有正确打印文件名。为了确保它确实是 unicode,我检查了:

    >>>os.listdir(u'listdir')[2]
    u'\u05e2\u05b4\u05d1\u05b0\u05e8\u05b4\u05d9\u05ea.txt'
    

    【讨论】:

    • 我认为这与 Windows 以 Unicode 格式存储所有文件名有关。查看我自己的部分答案
    • 很好奇。如果我只是将 pf 传递给打印,它会引发编码异常。它必须期待 ascii
    • 我认为 piro 已经确定了它(在对这个问题的另一个答案的评论中)。这是标准输出的编码。
    【解决方案3】:

    嗯,在some digging 之后,似乎在提供 os.listdir 一个 unicode 字符串时,这有点工作:

    files = os.listdir(u'test_source')
    
    for f in files:
    
        pf = os.path.join(u'test_source', f)
        print pf.encode('ascii', 'replace'), os.path.exists(pf)
    

    ===>

    test_source\ex True
    test_source\joe True
    test_source\mie.txt True
    test_source\__()'''.txt True
    test_source\????.txt True
    

    这里有一些重要的观察:

    • Windows XP(与所有 NT 衍生产品一样)以 unicode 存储所有文件名
    • os.listdir(和类似的函数,如 os.walk)应该传递一个 unicode 字符串,以便正确使用 unicode 路径。以下是上述链接的引述:

    os.listdir(),返回文件名, 提出了一个问题:它是否应该返回 文件名的 Unicode 版本,或 它应该返回 8 位字符串吗 包含编码版本? os.listdir() 将两者都做,具体取决于 关于您是否提供了目录 路径为 8 位字符串或 Unicode 细绳。如果你传递一个 Unicode 字符串 作为路径,文件名将被解码 使用文件系统的编码和 Unicode 字符串列表将是 返回,同时传递一个 8 位路径 将返回 8 位版本的 文件名。

    • 最后,print 需要一个 ascii 字符串,而不是 unicode,因此必须将路径编码为 ascii。

    【讨论】:

    • print 似乎对所有环境中的 ascii 并不挑剔。看我的回答。
    • print 打印 unicode 没有问题:问题可能出在 stdout 编码上。如果控制台是 unicode 则没有问题,否则需要显式编码。
    • 那太好了。应该意味着如果您使用正确的编码集打印到文件句柄,您可以在 Windows 上报告健全的文件名。 “替换”错误处理程序只是向我发出失败的信号。 =)
    【解决方案4】:

    问号是在无法以特定编码表示 unicode 字符时显示的或多或少的通用符号。您在 Windows 下的终端或交互式会话可能正在使用 ASCII 或 ISO-8859-1 或其他东西。所以实际的字符串是 unicode,但它被翻译成 ????打印到终端时。这就是为什么它适用于 PEZ,使用 OSX。

    【讨论】:

    • 可以让windoze终端显示unicode吗? OSX 做了什么来很好地展示它?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-06
    • 2020-11-30
    • 2018-11-22
    • 2018-01-16
    • 1970-01-01
    • 2013-11-08
    • 1970-01-01
    相关资源
    最近更新 更多