如何处理OSError: [Errno 36] 文件名过长

12

在处理尝试创建已存在的文件或尝试使用不存在的文件时发生的错误时,抛出的 OSError 具有子类 (FileExistsError, FileNotFoundError)。我找不到针对文件名过长这种特殊情况的子类。

具体的错误信息为:

OSError: [Errno 36] File name too long: 'filename'

我想捕获当文件名过长时发生的OSError,但仅当文件名过长时才这样做。我不想捕获其他可能发生的OSError。有没有办法实现这个目标?

编辑:我知道可以通过检查文件名长度来解决此问题,但是最大文件名长度因操作系统和文件系统而异,我不认为这是一个“干净”的解决方案。


可能是Python创建长文件时IOError异常的重复问题。 - NuclearPeon
@NuclearPeon:不是的。那是Windows特定的,那里的答案并没有回答这个问题。我在问题中指明了这一点。 - Max Matti
你可以尝试获取最大的文件名路径,虽然没有确定的方法来做到这一点。请查看此链接:https://code.activestate.com/lists/python-list/210662/ - 检查文件名的长度,并在太长时通知用户。否则,像已经列出的那样,使用try/except是最好的选择。 - NuclearPeon
我特别询问如何捕获确切的错误。我不想事先检查长度,因为存在竞态条件和最大文件名长度的不一致性(如问题所述)。 - Max Matti
我看到缩小OSError的唯一其他方法是在抛出异常时检查第三个参数。请参见此处的文档:https://docs.python.org/2/library/exceptions.html#exceptions.OSError - 相关信息:“对于涉及文件系统路径(例如chdir()或unlink())的异常,异常实例将包含第三个属性filename,该属性是传递给函数的文件名。”您可能不得不得出结论,Python没有确定要做什么的方法。提交错误报告。 - NuclearPeon
发现另一个可能会对你有帮助的SO问题;https://dev59.com/Co_ea4cB1Zd3GeqPPYfn - 步骤1:从这个问题中获取最大长度。步骤2:在你的OSError except块中,检查路径和文件名长度。步骤3:如果它超过了确定的长度,那么你就有了文件大小过长的条件。希望这可以帮到你。 - NuclearPeon
2个回答

17

只需检查捕获的异常的errno属性即可。

try:
    do_something()
except OSError as exc:
    if exc.errno == 36:
        handle_filename_too_long()
    else:
        raise  # re-raise previously caught exception

为了可读性,您可以考虑使用来自errno内置模块的适当常量,而不是硬编码常量。


但是我也捕获了其他我“特别”不想捕获的OSError - Max Matti

8
你可以指定如何捕获特定错误,例如errno.ENAMETOOLONG
针对你的问题,...
try:
    # try stuff
except OSError as oserr:
    if oserr.errno != errno.ENAMETOOLONG:
        # ignore
    else:
        # caught...now what?

针对您的评论...

try:
    # try stuff
except Exception as err:
    # get the name attribute from the exception class
    errname = type(err).__name__
    # get the errno attribute from the exception class
    errnum = err.errno
    if (errname == 'OSError') and (errnum == errno.ENAMETOOLONG):
        # handle specific to OSError [Errno 36]
    else if (errname == 'ExceptionNameHere' and ...:
        # handle specific to blah blah blah
    .
    .
    .
    else:
        raise # if you want to re-raise; otherwise code your ignore

这将捕获由try中错误引起的所有异常。然后,它检查__name__是否与任何特定异常和任何其他您想指定的条件匹配。

您应该知道,如果遇到错误,除非指定具体异常,否则无法避免except


但是我也捕获了其他我“特别”不想捕获的OSError - Max Matti
@MaxMatti 要“捕获”错误,必须“处理”它。if/else设置条件,即如果异常的errno属性不等于(!=),则编写代码忽略它(无论您选择如何处理);否则,您已经“捕获”了正确的异常...现在请“处理”它。 - pstatix
@MaxMatti 假设你有两个错误:E1和E2。在你的try/except中,你只想捕获E2,这是你目前关注的错误。你知道类型(OSError),但这不是except语句的工作方式。它是一个内置,因此您必须引用errno模块以获取其映射的错误代码。但是,如果你得到的第一个错误是E1呢?因为OSError是内置的,所以没有OSError.ENAMETOOLONG可以在except中指定。在发布的两个答案中,如果不是E2,你都可以继续前进。 - pstatix
@MaxMatti 只是因为你检查 OSError 是否是你想要处理的那个,并不会损害代码。无论在 try 语句中执行什么,如果遇到错误,都会受到 except 的影响。没有 except OSError as oserr if oserr.errno == errno.ENAMETOOLONG - pstatix
@MaxMatti 请检查修改,是否更符合您的想法? - pstatix
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接