在atexit处理程序之前清理Python记录器

时间:2014-04-22 23:15:29

标签: python logging scope atexit

我想使用Python的logging module在启动和关闭代理时显示消息。使用atexit module清理代理。但是,看起来在代理之前清理了记录器。我怎样才能获得预期的行为?这是一个有效的例子:

import atexit
import logging
logging.basicConfig()
LOG = logging.getLogger()
LOG.level = logging.INFO

class Program(object):
    def __init__(self):
        LOG.info("Hello")

    def __del__(self):
        LOG.info("Bye")

p = Program()

def cleanup(proxy):
    del proxy

atexit.register(cleanup, p)

从shell运行脚本的输出:

  

信息:根:您好
  异常AttributeError:“'NoneType'对象在<bound method Program.__del__ of <__main__.Program object at 0x7f467c9aabd0>>忽略

中没有属性'info'”

在不同版本和操作系统中具有相同的行为。

2 个答案:

答案 0 :(得分:3)

简短的回答是你can't rely on __del__ ever being called 1 - 而且,通过扩展,你不能依赖当时设置的任何环境。

我可以建议一个上下文管理器吗?

class Program(object):
    def __init__(self):
        self._finalized = False
        LOG.info('Hello')
    def __enter__(self):
        return self
    def __exit__(self, *args):
        self.__del__()
        self._finalized = True
    def __del__(self)
        if self._finalized:
            return
        LOG.info('Bye')

with Program() as p:
    ...

1 请注意段落末尾有关解释器关闭的条款和关于&#34;不稳定情况的红色警告框&#34;在__del__被占用的时候。

答案 1 :(得分:2)

你的问题是Python在解释器关闭期间(在3.4之前的版本中)将模块属性设置为None,并且你无法保证获得&#34;再见&#34;出。您可以通过将__del__定义为

来避免错误消息
def __del__(self):
    if LOG:
        LOG.info('Bye')