Python 如何实现电子邮件线程化 Class
Python How to Implement Threading of my Email Class
我有一封相当大的电子邮件 class,它构建并发送各种带有 mime、附件等的电子邮件。一切正常,但它是从我的主循环中调用的,使用 smtplib 的 sendmail 方法有时会阻塞几个秒因为另一端的问题。
我想 运行 将代码放在新线程中,这样我的主循环就可以继续运行。
我试过两种方法都没有成功:
使用线程
调用我的class
从 Thread
继承我的 V1 class
也不停止拦截。下面是我的 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
更可取。
我有一封相当大的电子邮件 class,它构建并发送各种带有 mime、附件等的电子邮件。一切正常,但它是从我的主循环中调用的,使用 smtplib 的 sendmail 方法有时会阻塞几个秒因为另一端的问题。 我想 运行 将代码放在新线程中,这样我的主循环就可以继续运行。
我试过两种方法都没有成功:
使用线程
调用我的class从 Thread
继承我的 V1 class
也不停止拦截。下面是我的 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
更可取。