Python 如何实现电子邮件线程化 Class

Python How to Implement Threading of my Email Class

我有一封相当大的电子邮件 class,它构建并发送各种带有 mime、附件等的电子邮件。一切正常,但它是从我的主循环中调用的,使用 smtplib 的 sendmail 方法有时会阻塞几个秒因为另一端的问题。 我想 运行 将代码放在新线程中,这样我的主循环就可以继续运行。

我试过两种方法都没有成功:

也不停止拦截。下面是我的 class (V1) 的工作框架和我尝试过的内容。成功将看到“完成”在“开始”之后立即出现,而不是等待 3 秒让 sendmail 完成。 希望有一个简单的方法来做到这一点...

from time import sleep
from threading import Thread

class EMailv1():
    def __init__(self):
        self._from_address = 'a@b.com'
        self._to_addresslist = []

    def buildmessage(self, **kwargs):
        message ={}
        return message

    @staticmethod
    def sendmail(message):
        sleep(5)
        return

class EMailv2(Thread):
    def __init__(self):
        Thread.__init__(self)
        self._from_address = 'a@b.com'
        self._to_addresslist = []

    def run(self):
        pass

    def buildmessage(self, **kwargs):
        message ={}
        return message

    @staticmethod
    def sendmail( message):
        sleep(3)
        return


if __name__ == "__main__":
    print('Starting V1 class send in current manner, which blocks if smtplib cannot deliver mail')
    email =EMailv1()
    msg = email.buildmessage(a='a',b='b')
    email.sendmail(msg)
    print('v1 Done after sendmail sleep finishes')

    print('Starting  threaded call to send V1 class')
    email = EMailv1()
    msg = email.buildmessage(a='a',b='b')
    t = Thread(target=email.sendmail(msg))
    t.start()
    print('Threaded call of V1 Done after sendmail sleep finishes')

    print('Starting V2 class inheriting Thread')
    email = EMailv2()
    msg = email.buildmessage(a='a',b='b')
    email.start()
    email.sendmail(msg)
    print('V2 Done after sendmail sleep finishes')

在你的第二个版本中,而不是

t = Thread(target=email.sendmail(msg))

你应该做的

t = Thread(target=email.sendmail, args=[msg])

按照你写的方式,它正在评估email.sendmail(msg) before 构造线程,这就是为什么你看到你在继续之前等待 5 秒。

相反,您应该分别向线程传递目标函数和参数,而不对它们求值。

这是一个固定的和最小化的版本:

from time import sleep
from threading import Thread

class EMailv1():
    def __init__(self):
        self._from_address = 'a@b.com'
        self._to_addresslist = []

    def buildmessage(self, **kwargs):
        message ={}
        return message

    @staticmethod
    def sendmail(message):
        sleep(5)
        print("Launched thread: I'm done sleeping!")
        return

if __name__ == "__main__":
    print('Main thread: Starting  threaded call to send V1 class')
    email = EMailv1()
    msg = email.buildmessage(a='a', b='b')
    t = Thread(target=email.sendmail, args=[msg])
    t.start()
    print("Main thread: I have created the thread, and am done.")

输出:

Main thread: Starting  threaded call to send V1 class
Main thread: I have created the thread, and am done.
Launched thread: I'm done sleeping!

话虽如此,我还建议您看一下 Python 中提供的一些用于执行多线程工作的抽象。例如,看看像 ThreadPoolExecutor 这样的特性——这些特性通常比直接使用 Thread 更可取。