Python 2.7 应用程序结束时不调用_del__的情况

Python 2.7 应用程序结束时不调用_del__的情况,python-2.7,garbage-collection,Python 2.7,Garbage Collection,ClassCumulativeSender在应用程序结束时发送电子邮件。我读到了垃圾收集器和\uuuuu del\uuu的问题,我想知道在应用程序结束时是否会调用\uuuu del\uuu的\uuuuu del\uu静态累积子对象的以及为什么 CumulativeSender.py: import smtplib; _staticCumulativeSenderObject = None; class CumulativeSender(object): def __init__(

Class
CumulativeSender
在应用程序结束时发送电子邮件。我读到了垃圾收集器和
\uuuuu del\uuu
的问题,我想知道在应用程序结束时是否会调用
\uuuu del\uuu
\uuuuu del\uu
静态累积子对象的
以及为什么

CumulativeSender.py:

import smtplib;

_staticCumulativeSenderObject = None;


class CumulativeSender(object):

    def __init__(self):

        recipients['sender'] = 'from@domain.com';
        recipients['emails'] = ['to@domain.com'];
        recipients['subject'] = 'Test Email';
        recipients['smtp_host'] = 'localhost';

        self.message = "";
        self.fromaddr = recipients['sender'];
        self.toaddrs  = recipients['emails'];
        self.subject = recipients['subject'];

        self.server = smtplib.SMTP(recipients['smtp_host']);

    def __del__(self):
        if(self.message):
            msg = ("From: %s\r\nTo: %s\r\n" % (self.fromaddr, ", ".join(self.toaddrs))) + "Subject: " + self.subject + "\r\n\r\n" + self.message;
            self.server.sendmail(self.fromaddr, self.toaddrs, msg);
        self.server.quit();

    def immediateSend():
        global _staticCumulativeSenderObject;
        if(_staticCumulativeSenderObject is not None):
            toDelete = _staticCumulativeSenderObject;
            _staticCumulativeSenderObject = None;
            del toDelete;


    immediateSend = staticmethod(immediateSend);


    def addEvent(msg):
        global _staticCumulativeSenderObject;
        if(_staticCumulativeSenderObject is None):
            _staticCumulativeSenderObject = CumulativeSender();
        _staticCumulativeSenderObject.message += msg + "\r\n";

    addEvent = staticmethod(addEvent);


    def addAlert(msg, code = None):
        CumulativeSender.addEvent(buildMessage("Allert",msg,code));

    addAlert = staticmethod(addAlert);


    def addError(msg, code = None):
        CumulativeSender.addEvent(buildMessage("Error",msg,code));

    addError = staticmethod(addError);
简单使用:

import CumulativeSender;
CumulativeSender.CumulativeSender.addAlert("alert1", 345);
CumulativeSender.CumulativeSender.addAlert("alert2", 346);

或者,也许还有其他方法可以实现我想要的功能?

您需要有一个非常好的理由来覆盖
\uuu del\uu
。在绝大多数情况下,弊大于利。使用您选择的Web搜索引擎,您可以找到大量关于
\uuu del\uuu
的阅读资料

您没有解释为什么您更喜欢隐式方法,而不是添加
send()
方法并在发送电子邮件时显式调用它。这将是我的最终建议

但是,相信您确实有充分的理由使用隐式方法,您可以通过定义
\uuuuu enter\uuuu
\uuuu exit\uuuu
方法(或使用快捷方式)来定义。用法类似于:

with CumulativeSender(...) as sender:
    sender.addEvent(...)
    sender.add...(...)
    sender.add...(...)
退出此块时,将调用
\uuuu exit\uu
方法。你可以在那里发送电子邮件

请注意,如果异常离开该块,也会调用
\uuuuuuuu exit\uuuuuu
,因此,如果引发异常(可能不会),您应该决定是否发送


但是再次强调,.

你永远不应该依赖于
\uu del\uu
。但您的问题是“何时不调用
\uu del\uu
方法?”。这实际上很简单,只要有指向对象的循环引用。在这种情况下,Python无法区分应该首先删除哪个对象,因此Python根本不会调用任何
\uuu del\uu
方法。更难的问题是什么时候你可以得到一个循环引用,但这并不能解决你的问题

\uu del\uu
方法的错误使用通常来自

您的代码将运行良好,直到有人从循环引用中涉及的对象引用了
\u staticCumulativeSenderObject
。但是,即使它看起来像一个私人的,没有人应该做任何参考,这是一个糟糕的设计。此代码将完全执行atexit模块的功能

import atexit

@atexit.register
def _sendAtExit():
    global _staticCumulativeSenderObject
    if _staticCumulativeSenderObject:
         #do what your __del__ is doing
        _staticCumulativeSenderObject.send_and_close()
        _staticCumulativeSenderObject=None

除非你有很好的理由,否则不要覆盖
\uuu del\uuu
。如果您不确定,您不确定。请提出一些将取代
\uu del\uuu
的建议。谢谢您的回答。此类的静态方法(
addAlert
addError
)将在代码中的许多不同位置使用(不同的文件和不同的类),但有多个入口点(多个应用程序)。我不能保证有人会在应用程序结束时调用
send()
。类用户不真正使用类对象,只使用类的静态方法。对他来说真的没有什么牵连。他使用该方法,并在应用程序结束时刷新缓冲区。禅宗的下一句话:简单比简单好complex@Logman您的
main()
函数是什么样子的?为什么不能显式调用
send()
作为
main
的最后一行?此外,在这方面,你认为“简单”和“复杂”是什么?有多个主要功能,它不是一个单一的应用。看看这个类,它更像是更复杂系统的模块。当我使用函数(某物)时,它真的很简单,但当我需要自己管理某个对象时,它更复杂。Thx的答案不同于“
\uu del\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
是魔鬼”,并且为我提供了一些可以代替
的东西