我有一个Django应用程序,在我的一个视图中,我实际上正在对发送电子邮件的函数进行异步调用。我使用了threading.thread(带有start())以及一个名为after_response的小型django包,基本上也是这样。
以下是我所做的:
def my_synchronous_function(instance):
send_email_asynchronous.after_response(instance.id)
return "We are done here, but async call will continue."
@after_response.enable
def send_email_asynchronous(instance_id):
time.sleep(5)
print "Async has started"
instance = Instance.objects.get(pk=instance_id)
subject = "A subject"
ctx = {'username': instance.username}
message = get_template("email-template.html").render(ctx)
msg = EmailMessage(subject, message, to=[instance.email], from_email='loic@example.com')
print "about to send email"
time.sleep(5)
msg.content_subtype = 'html'
msg.send()
print "message sent"
这个代码在运行django manage.py runserver时效果很好;当使用nginx + gunicorn时它也可以正常工作。但是,我注意到在使用UWSGI和Nginx时,send_email_asynchronous函数永远不会被调用。使用after_response以及更长的线程时也是如此。线程版本:
class SendNotification(threading.Thread):
"""
Sends notifications async.
"""
def __init__(self, instance_id):
"""
Sends notifications asynchronously provided an instance id.
"""
print "instance id: %s" % instance_id
self.instance = Instance.objects.get(pk=instance_id)
super(SendNotification, self).__init__()
def run (self):
time.sleep(5)
print "Async has started"
subject = "A subject"
ctx = {'username': self.instance.username}
message = get_template("email-template.html").render(ctx)
msg = EmailMessage(subject, message, to=[self.instance.email], from_email='loic@example.com')
print "about to send email"
time.sleep(5)
msg.content_subtype = 'html'
msg.send()
print "message sent"
这是以下列方式启动的: sendNotification时(instance.id)。开始()
再次,与开发服务器和#34; runserver"一起使用,也适用于gunicorn,但不适用于uwsgi,我有点疑惑为什么会发生这种情况。使用uwsgi,我实际上从 init 中看到了print语句,但是没有看到run方法中的print语句,当然也没有看到电子邮件。由于这个问题,我已经转而使用gunicorn了,所以我更多的是出于好奇而提出要求。
谢谢,
答案 0 :(得分:2)
您没有发布您的uWSGI配置,但考虑到这是关于未运行的后台线程,您在启动uWSGI时很有可能need to add --enable-threads
:
如果没有线程启动uWSGI,Python GIL就不会 启用,因此应用程序生成的线程永远不会运行。您 可能不喜欢那个选择,但要记住uWSGI是一个 与语言无关的服务器,所以它的大部分选择都是为了 保持它“不可知”。
但不要担心,uWSGI基本上没有选择 无法通过选项更改的开发人员。
如果您想在不启动的情况下维护Python线程支持 您的应用程序的多个线程,只需添加--enable-threads 选项(或ini样式中的enable-threads = true)。