1

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

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 运行脚本的输出:

INFO:root:Hello
Exception AttributeError: "'NoneType' object has no attribute 'info'"<bound method Program.__del__ of <__main__.Program object at 0x7f467c9aabd0>>被忽略

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

4

2 回答 2

3

简短的回答是,您不能依赖__del__被称为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请注意段落末尾关于解释器关闭的条款以及关于何时__del__被引发的“不稳定情况”的红色警告框。

于 2014-04-22T23:32:59.763 回答
2

您的问题是 Python 将模块属性设置为None在解释器关闭期间(在 3.4 之前的版本中),并且您不能保证让“再见”出来。__del__您可以通过定义为来避免错误消息

def __del__(self):
    if LOG:
        LOG.info('Bye')
于 2014-04-23T05:32:38.317 回答