静态类成员/类引用的生命周期? [英] Lifetime of static class members/class references?

查看:188
本文介绍了静态类成员/类引用的生命周期?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

要求展示如何为特殊记录器的旧栗子做类似单例的解决方案。我仍然不遗余力地指出不做这种事情的原因。

I was asked to show how to do a singleton like solution for the old chestnut of a special logger. At pains to point out the reasons for not doing this sort of thing, still, I tried.

这样做,我有一个静态的类成员意外消失了。

In doing so, I have a static class member disappearing unexpectedly.

使用此类声明:

epiLogger.py:

epiLogger.py:

import logging

class epiLogger():
    _initialised = {}
    _finalised = {}

    def __init__(self, name):
        self.logger = logging.getLogger(name)
        self.name = name
        if not epiLogger._initialised.get(name):
            self.logger.addHandler(logging.StreamHandler())
            self.logger.setLevel(logging.INFO)
            self.logger.info('** My Prologue **')
            epiLogger._initialised[self.name] = True

    def info(self, the_info):
        self.logger.info(the_info)
        print epiLogger._finalised.get(self.name)

    def __del__(self):
        print "destructing", self.name
        if not epiLogger._finalised.get(self.name):
            print "first destruction"
            self.logger.info('** My Epilogue **')
            epiLogger._finalised[self.name] = True

这些测试文件为:

bar.py:

from epiLogger import *

a = epiLogger("bar")

a.info("foo!")
a.info("bar!")
a.info("party!")

test.py:

import bar

我知道了

~ mgregory$ python test.py
** My Prologue **
foo!
None
bar!
None
party!
None
destructing bar
Exception AttributeError: "'NoneType' object has no attribute '_finalised'" in <bound method epiLogger.__del__ of <epiLogger.epiLogger instance at 0x1004a48c0>> ignored
~ mgregory$  

但是如果我只运行bar.py文件:

But if I run just the bar.py file:

~ mgregory$ python bar.py
** My Prologue **
foo!
None
bar!
None
party!
None
destructing bar
first destruction
** My Epilogue **
~ mgregory$ 

似乎一个间接级别导致对类本身的引用(访问类变量)已变为无。

It seems that one level of indirection has resulted in the reference to the class itself (to access the class variable) has become "None".

我尝试了一个更简单的测试用例,并且它不会以这种方式失败(!)

I tried a simpler test case, and it does not fail in this way (!)

frob.py:

class frob():    
    _nasty_global_thingy = True

    def __init__(self):
        print "initialising a foo", frob._nasty_global_thingy

    def __del__(self):
        print "destroying a foo", frob._nasty_global_thingy

bar.py:

from frob import *

a = frob()
print a

这不会失败

我了解这是不尝试此类操作的众多原因之一,但我想了解一下

I understand that this is one of many reasons not to try this sort of thing, but I would like to understand what is going on, nonetheless.

推荐答案

在Python出口清理模块全局变量,并且您的类引用为在运行 __ del __ 钩子时已经消失了。

Module globals are cleaned up on Python exit, and your class reference is already gone by the time the __del__ hook is run.

不要指望全局变量在那里。而是使用 type(self)来获取类引用:

Don't count on globals still being there. Rather, use type(self) to get the class reference:

def __del__(self):
    print "destructing", self.name
    cls = type(self)
    if not cls._finalised.get(self.name):
        print "first destruction"
        self.logger.info('** My Epilogue **')
        cls._finalised[self.name] = True

这在 object .__ del __ 挂钩文档

This is documented in the big Warning section on the object.__del__ hook documentation:


另外,当响应删除模块而调用 __ del __()时(例如,执行程序时) , __ del __()方法引用的其他全局变量可能已经被删除或正在拆除中(例如,进口机械关闭)。因此, __ del __()方法应该达到维护外部不变性所需的绝对最小值。

Also, when __del__() is invoked in response to a module being deleted (e.g., when execution of the program is done), other globals referenced by the __del__() method may already have been deleted or in the process of being torn down (e.g. the import machinery shutting down). For this reason, __del__() methods should do the absolute minimum needed to maintain external invariants.

请注意,模块全局变量在词典中维护,因此清除模块全局变量的顺序应受清除时依赖于词典的当前实现和Python版本的顺序约束。

Take into account that module globals are maintained in a dictionary, and thus the order in which they are cleared is subject to the current implementation-and-Python-version-dependent order of the dictionary when being cleared.

这篇关于静态类成员/类引用的生命周期?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆