2011-11-14 24 views
3

这可能是一个开放式或尴尬的问题,但我发现自己陷入越来越多的异常处理问题,我不知道处理它们的“最佳”方法。正确处理logging.config.fileConfig抛出的IOError?

如果您尝试使用不存在的文件配置FileHandler,则Python的日志记录模块会引发IOError。该模块不处理这个异常,但只是提出它。通常情况下,文件路径不存在(因此文件不存在),所以如果我们想要处理异常并继续,我们必须沿路径创建目录。

我想让我的应用程序正确处理这个错误,因为每个用户都问过为什么我们不为他们制作正确的目录。

我决定处理这个问题的方式可以在下面看到。

done = False 
while not done: 
    try: 
     # Configure logging based on a config file 
     # if a filehandler's full path to file does not exist, it raises an IOError 
     logging.config.fileConfig(filename) 

    except IOError as e: 
     if e.args[0] == 2 and e.filename: 
      # If we catch the IOError, we can see if it is a "does not exist" error 
      # and try to recover by making the directories 

      print "Most likely the full path to the file does not exist, so we can try and make it" 
      fp = e.filename[:e.rfind("/")] 

      # See http://stackoverflow.com/questions/273192/python-best-way-to-create-directory-if-it-doesnt-exist-for-file-write#273208 for why I don't just leap 
      if not os.path.exists(fp): 
       os.makedirs(fp) 

     else: 
      print "Most likely some other error...let's just reraise for now" 
      raise 
    else: 
     done = True 

我需要循环(或递归我想)由于存在需要配置,因此需要ÑIOErrors被升高和用于此方案中校正ÑFileHandlers。

这是正确的方法吗?有没有更好,更Python的方式,我不知道或不明白?

+0

我很困惑,不存在的文件是否是配置文件(传递给'fileConfig',就像你的源文件一样)或者它是否是日志文件的名称(根据你的问题的文本)尝试使用不存在的文件配置FileHandler“)。我的答案是后者。通常,在指定文件时(无论是配置文件还是日志文件),需要确保很多事情 - 例如,文件可能已经存在,但由于权限问题而不可读或不可写。没有一个适合所有人的解决方案,这就是为什么你有时需要推出自己的产品。 –

+0

我指的是日志文件的名称,我需要从日志记录配置文件中取出来检查它是否存在。必须在代码中的此处获取该信息是不方便的。我同意你的观点,即在启动时进行检查是理想的。也许我真正的问题是为什么记录模块不处理用户的这些类型的异常? – dicato

+0

由于日志记录模块需要将日志文件名称指定为可写入文件,并且存在于该目录中。这种行为符合最小惊喜的原则。一个典型的文本编辑器(例如,Windows上的记事本或Linux上的gedit),当在不存在的目录中使用文件名进行调用时,不会自动为您创建文件。记事本给出错误信息; gedit不会以该名称保存该文件,但会在您单击“保存”时提示您输入位置。 –

回答

1

这不是特定于日志记录模块的内容:通常,Python代码不会自动为您自动创建中间目录;你需要做的这个明确使用os.makedirs(),通常是这样的:

if not os.path.exists(dirname): 
    os.makedirs(dirname) 

您可以替换与子类,可以做你需要的检查记录提供的标准FileHandler,在必要时,创建日志文件的目录使用os.makedirs()。然后,您可以在配置文件中指定此处理程序,而不是标准处理程序。

+0

因此,为了正确处理记录模块中的异常,我需要继承模块?虽然我同意设计是合理的,但它似乎是处理异常(或一组异常)的复杂方式。 – dicato

0

假设只需要在应用程序执行开始时执行一次,我将只需os.makedirs()所有需要的目录,而不先检查它们的存在,或者甚至等待记录模块发出错误。如果您尝试启动记录器时出现错误,则可以按照您可能已经执行的方式进行处理:打印错误,禁用记录器。您试图创建该目录,超越了自己的想法。如果用户给你提供虚假信息,那么你的情况并不比现在差,而且在绝大多数情况下你都会更好。

+0

这种方法令我担忧的是我需要解析,然后遍历日志配置文件,检查args变量,如果它是文件处理程序,并采取行动。虽然这不是一个挑战,但它似乎是解决问题的漫长解决方案。为什么我需要这样做?为什么记录模块不能为我做这件事? – dicato

+0

Hrm,是啊,我一开始并没有注意到你传递给日志文件的文件名是那些日志配置文件而不是日志文件。它看起来像Vinay有一个建议使用自定义FileHandler这可能是一个更好的方法。 – kindall

+0

虽然Vinay的解决方案当然是一个好主意,但是您认为这对于这个问题来说是否有点矫枉过正? – dicato