14

我正在编写一个必须移动一些文件的脚本,但不幸的是,它似乎不太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

4

4 回答 4

17

嗯,经过一番挖掘,似乎在提供 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。
于 2009-01-30T21:40:06.730 回答
3

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

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

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

请注意,当 os.listdir() 返回字符串列表时,将省略无法正确解码的文件名,而不是引发 UnicodeError。

于 2009-01-30T21:25:24.513 回答
1

在 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'
于 2009-01-30T21:38:37.683 回答
0

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

于 2009-01-30T22:27:12.577 回答