【问题标题】:os.walk() not processing subdirectories when using UNC pathsos.walk() 在使用 UNC 路径时不处理子目录
【发布时间】:2016-08-10 20:33:39
【问题描述】:

我在 Windows 上的 python 2.7.8 中使用 os.walk() 时遇到问题。

当我为它提供“正常”路径(例如 "D:\Test\master")时,它会按预期工作。但是,当我为它提供 UNC 路径(例如 "\\?\D:\Test\master")时,它会按预期报告根目录,但不会深入到子目录,也不会引发异常。

我的研究:我在help page 上读到os.walk() 接受一个函数参数来处理错误。默认这个参数是None,所以不会报错。

我传递了一个简单的函数来打印错误并收到每个目录的以下内容。

def WalkError(Error):
    raise Exception(Error)

堆栈跟踪:

Traceback (most recent call last):
  File "Compare.py", line 988, in StartServer
    for root, dirs, files in os.walk(ROOT_DIR,True,WalkError):
  File "C:\Program Files (x86)\Python2.7.8\lib\os.py", line 296, in walk
    for x in walk(new_path, topdown, onerror, followlinks):
  File "C:\Program Files (x86)\Python2.7.8\lib\os.py", line 281, in walk
    onerror(err)
  File "Compare.py", line 62, in WalkError
    raise Exception(Error)
Exception: [Error 123] The filename, directory name, or volume label syntax is incorrect: '\\\\?\\D:\\Test\\master\\localization/*.*'

【问题讨论】:

  • 您实际上可以发布自己问题的答案。 blog.stackoverflow.com/2011/07/…
  • \\?\ 前缀不是 UNC 路径。 UNC 路径(例如 \\server\share)使用扩展路径前缀变为 \\?\UNC\server\share。这个\\?\ 前缀绕过了正常的路径处理。 Windows 只是将它替换为 NT DOS 设备前缀\??\,它让对象管理器在登录会话 DOS 设备中搜索设备,然后搜索\Global?? 对象目录。这意味着 \\?\ 路径必须是 unicode 字符串,因为 NT 路径是 Unicode,并且必须只使用反斜杠作为路径分隔符,因为正斜杠只是 NT 命名空间中的常规名称字符。
  • 如果您使用'//?/D:/Test/master',它不会绕过常规路径处理,并且路径仅限于MAX_PATH(260)个字符。使用u'\\\\?\\D:\\Test\\master'
  • @eryksun - 这是正确的解决方案。我的代码都是 unicode,所以我认为这不是问题,但它通过套接字传输路径名,因此 unicode“格式”丢失了。接收端从套接字中获取字节并将它们放入默认编码的字符串中。我使用该字符串并将其用作顶部来遍历目录,但它失败了。转换为 unicode 并运行 walk 使其完美运行。 - 谢谢。

标签: python windows os.walk


【解决方案1】:

原作者的回答(最初作为对问题的编辑发布):

即时更新:在检查\lib\os.py的过程中,发现错误源于os.listdir()。我搜索了上述与os.listdir() 相关的错误消息,发现this solution 对我有用。

看起来如果您要使用带有os. 模块的UNC 样式路径,它们需要Unix 化(将它们的\ 转换为/)。 \\\\?\\D:\\Test\\master\\ 变为 //?/D:/Test/master/(注意:您不再需要转义方便的 \)。

这与UNC 'spec' 背道而驰,因此请注意您是否正在使用其他尊重 Microsoft UNC 实施的模块。

(对不起,自我解决,我正要关闭标签,但觉得这里有其他地方找不到的知识。)

【讨论】:

  • UNC 路径不存在此类问题,\\?\ 前缀甚至不是 UNC 路径。您不能在 NT 路径中使用斜杠作为路径分隔符,Python 通过在 8 位 str 分支中附加 /*.* 违反了这一点。如果它附加了\*.*,您将能够在不是unicode 字符串的路径中使用\\?\,但由于旧版本的Windows 将8 位ANSI 字符串解码为施加此限制的静态分配缓冲区。无论如何,Python 的 listdir 的 8 位字符串分支使用堆栈分配的缓冲区,该缓冲区也限制为 260 个字符。
  • @eryksun 我没有管理这个答案,我不相信它,我没有写这个。它在审查队列中被标记为删除,它似乎对 OP 有所帮助,所以我只是挽救了它。随意编辑它,甚至更好 - 发布您自己的答案。如果你这样做了,请通知我,以便我删除这个。谢谢! :)
  • 我有相关的答案herehere。我可以添加另一个答案来讨论在 Python 2 中使用 \\?\listdir,但只有当您尝试将它与 8 位 str 路径一起使用时才会出现问题,即使在 2.7 中也应该弃用,就像在 Python 3 中,bytes 路径在 Windows 中已弃用。
猜你喜欢
  • 1970-01-01
  • 2016-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-30
  • 1970-01-01
  • 2014-05-03
相关资源
最近更新 更多