Python 2.7 应用程序结束时不调用_del__的情况
ClassPython 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__(
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
是魔鬼”,并且为我提供了一些可以代替的东西