python 2.x:有条件地捕获异常(如果文件丢失则忽略优雅清理)

python 2.x:Conditionally Catching Exceptions (Ignore gracefully cleanup if the file is missing)

我有一个脚本可以清理共享位置超过 14 天的日志。现在这个脚本可以同时从不同的主机运行。在特定情况下,如果两个或多个主机尝试清理同一个文件,则只有一个会成功,而所有其他主机都会给出错误 "No such file or directory"。如果文件突然丢失,我如何更新代码以忽略正常清理。下面是执行清理的代码的一部分。 count 跟踪删除的文件数。

if os.stat(filename).st_mtime < current_time - 14 * 86400:
    try:
       os.remove(filename)
       count += 1
    except:
       logger.warning("Not able to delete the file %s" % filename)

一种方法是 "pass" 如果文件不存在则异常,但如果您无法删除文件则继续记录警告。如何包含此条件。

正如@Mark 建议的那样,您可以事先检查文件是否存在,然后将其删除,但这种方法仍然存在潜在的竞争条件。它可以发生在 os.stat 之后和 os.remove 之前的脚本实例之间。将所有代码引发错误移动到 try / except 应该可以完成这项工作。但是,据我所知,记录真实消息存在问题。附加标志 attempted_delete 应该对此有所帮助:

attempted_delete = False
try:
    if os.stat(filename).st_mtime < current_time - 14 * 86400:
         os.remove(filename)
         count += 1
         attempted_delete = True
except:
     if attempted_delete:
         logger.warning("Not able to delete the file %s" % filename)

没有例外(类型)列表的 except 子句是 catch-all:易于设置但难以使用。在这里你应该特别捕获(并忽略)一个 FileNotFoundError 并记录任何其他异常:

try:
   if os.stat(filename).st_mtime < current_time - 14 * 86400:
      os.remove(filename)
      count += 1
except FileNotFoundError:
   pass  # file has already been deleted: all is fine
except:
   logger.warning("Not able to delete the file %s" % filename)

以上是针对Python 3,当你使用Python 2时,你只能检查OSError,然后控制它的errno属性:

try:
   if os.stat(filename).st_mtime < current_time - 14 * 86400:
      os.remove(filename)
      count += 1
except OSError as e:
   if e.errno != errno.ENOENT:
      # do not log if file has already been deleted
      logger.warning("Not able to delete the file %s" % filename)
except:
   logger.warning("Not able to delete the file %s" % filename)