【问题标题】:Python IOError exception when creating a long file创建长文件时出现Python IOError异常
【发布时间】:2019-03-15 02:33:29
【问题描述】:

尝试使用“open (fname, 'w+')”打开新文件时,出现如下所示的 IOError。完整的错误信息如下。

该文件不存在,但我使用“os.access(dir_name, os.W_OK)”和“os.path.exists (dir_name)”验证该文件的父目录确实存在。

我想知道文件名对于 Windows 是否太长,或者我做错了什么。任何提示将不胜感激。非常感谢。

错误信息:

IOError: [Errno 2] 没有这样的文件或目录:'C:\Documents and Settings\Administrator\op_models\Corp_Network_Nov12\abcde_corporate_nov_12.project\abcde_corporate_nov_12-ctr.rptd.dir\ctr\Non 营业时间 Weeknights\hourly_data_for_2_weeks\1294897740\json.data\Link\0\Link 使用\analyzer393146160-data0.js'

【问题讨论】:

  • 谢谢。限制确实超过 260 个字符。 MSDN文章提到我们可以使用“\\?\”前缀作为长文件名,只是好奇是否有人知道我如何将前缀添加到文件名中。当我尝试执行简单的“+”操作时,在扫描单引号字符串时出现错误 EOL。 (fname = '\\?\' + fname)
  • 使用“\\\\?\\”。在这种情况下,原始字符串将不起作用。
  • 改用正斜杠。另见stackoverflow.com/faq#howtoask
  • 我尝试使用 "\\\\?\\" 和 "\\\\UNC\\?\\" 通过将它们附加到文件名并得到相同的异常。无论如何,当我尝试在 Windows 资源管理器中创建文件时,它不会让我创建文件(Windows 阻止我添加字符)。我猜这是系统限制?

标签: python filenames ioerror


【解决方案1】:

在 Windows API 中,最大路径长度限制为 260 个字符。

http://msdn.microsoft.com/en-us/library/aa365247%28v=vs.85%29.aspx

更新:在路径前添加“\\?\”。

【讨论】:

  • ...结合了非常混乱的错误值;它应该是 ENAMETOOLONG,而不是 ENOENT。我认为这是每个人在其职业生涯中至少有一次困惑的那些晦涩难懂的 Windows 错误之一。
  • 非英语语言呢?我觉得最大值更低。
【解决方案2】:

这是一些对我有用的相关代码(我有很长的文件名和路径):

for d in os.walk(os.getcwd()):
    dirname = d[0]
    files = d[2]
    for f in files:
        long_fname = u"\\\\?\\" + os.getcwd() + u"\\" + dirname + u"\\" + f
        if op.isdir(long_fname):
            continue
        fin = open(long_fname, 'rb')
        ...

请注意,对我而言,它仅适用于以下所有内容的组合:

  1. 在前面添加“\\?\”。

  2. 使用完整路径,而不是相对路径。

  3. 只使用反斜杠。

  4. 在 Python 中,文件名字符串必须是 unicode 字符串,例如 u"abc",而不是 "abc"。

另外请注意,由于某种原因,os.walk(..) 将一些目录作为文件返回,所以我在上面检查了这一点。

【讨论】:

  • 非常感谢您提到 Python 字符串必须是 Unicode 字符串 - 这救了我!
  • os.getcwd() 为我修复了它。必须是整个路径,而不仅仅是相对路径。
【解决方案3】:

你可以用这个猴子修补 tarfile 模块:

import tarfile

def monkey_patch_tarfile():
    import os
    import sys
    if sys.platform not in ['cygwin', 'win32']:
        return
    def long_open(name, *args, **kwargs):
    # http://msdn.microsoft.com/en-us/library/aa365247%28v=vs.85%29.aspx#maxpath
        if len(name) >= 200:
            if not os.path.isabs(name):
                name = os.path.join(os.getcwd(), name)
            name = "\\\\?\\" + os.path.normpath(name)
        return long_open.bltn_open(name, *args, **kwargs)
    long_open.bltn_open = tarfile.bltn_open
    tarfile.bltn_open = long_open

monkey_patch_tarfile()

【讨论】:

    【解决方案4】:

    如果不是文件名的长度,就是文件名的内容...

    Python 将 '\12' 视为控制序列。

    >>> fn='C:\Documents and Settings\Administrator\op_models\Corp_Network_Nov12\abcde_corporate_nov_12.project\abcde_corporate_nov_12-ctr.rptd.dir\ctr\Non Business Hours for Weeknights\hourly_data_for_2_weeks\1294897740\json.data\Link\0\Link Utilization\analyzer393146160-data0.js'
    >>> print fn
    C:\Documents and Settings\Administrator\op_models\Corp_Network_Nov12bcde_corporate_nov_12.projectbcde_corporate_nov_12-ctr.rptd.dir\ctr\Non Business Hours for Weeknights\hourly_data_for_2_weeks
    94897740\json.data\Link\Link Utilizationnalyzer393146160-data0.js
    

    对 Windows 文件名使用 raw strings 会有所帮助:

    >>> fn=r'C:\Documents and Settings\Administrator\op_models\Corp_Network_Nov12\abcde_corporate_nov_12.project\abcde_corporate_nov_12-ctr.rptd.dir\ctr\Non Business Hours for Weeknights\hourly_data_for_2_weeks\1294897740\json.data\Link\0\Link Utilization\analyzer393146160-data0.js'
    >>> print fn
    C:\Documents and Settings\Administrator\op_models\Corp_Network_Nov12\abcde_corporate_nov_12.project\abcde_corporate_nov_12-ctr.rptd.dir\ctr\Non Business Hours for Weeknights\hourly_data_for_2_weeks\1294897740\json.data\Link\0\Link Utilization\analyzer393146160-data0.js
    

    更新

    或者,使用正斜杠“/”而不是反斜杠“\”,因为它们适用于所有操作系统,并且可以省去在路径名末尾使用反斜杠的麻烦,就像在 cmets 中一样。

    另见os.path.join()

    更新 2

    问题的简化演示:

    >>> open('.\12\n\r\file.txt')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    IOError: [Errno 2] No such file or directory: '.\n\n\r\x0cile.txt'
    >>> open('./12/n/r/file.txt')
    <open file './12/n/r/file.txt', mode 'r' at 0x7ff83f98>
    
    C:\Users\johnysweb>copy .\12\n\r\file.txt con
    Blah
            1 file(s) copied.
    

    【讨论】:

    • 您最好始终使用正斜杠;它们在 Windows 中运行良好,并且生成的代码更有可能在其他平台上运行。
    • OP 使用了正确编码的文件路径。否则错误消息将不同 (TypeError)。
    • @cgohlke:请参阅我的第二次更新,它演示了 IOError 异常,其文本与 OP 报告的文本相同。
    • 我确实认为编码是正确的,因为我只是尝试了一个不同的文件名(带有整个路径的 sm.txt),它使我保持在 260 个字符的限制内,并且毫无例外地工作。我确实看到了正在创建的文件。
    • @Johnsyweb:我不怀疑使用错误编码的路径名会导致 IOError。但是,OP 使用的路径名包含一个 NULL 字节“\0”,这将导致 open 函数中出现 TypeError。 OP 手动键入 260+ 个字符的路径名也不太可能。更有可能是函数调用的结果。
    【解决方案5】:

    检查整个路径的长度,然后附加必要的 Windows 长路径格式。应该注意的是,这不适用于从远程目录访问数据,即以 '\\some_remote_location\..' 开头的路径,因此您需要在本地映射该目录才能使“长路径”工作。

    if len(path_and_file) > 250: #I think the max is 260 but I left a buffer :)
        path_and_file = '\\\\?\\'+path_and_file
    

    【讨论】:

      猜你喜欢
      • 2016-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多