Python Django的多线程

tom*_*ell 39 python django multithreading decorator python-multithreading

某些功能应在Web服务器上异步运行.发送电子邮件或数据后处理是典型的用例.

编写装饰器函数以异步运行函数的最佳(或最pythonic)方法是什么?

我的设置很常见:Python,Django,Gunicorn或Waitress,AWS EC2标准Linux

例如,这是一个开始:

from threading import Thread

def postpone(function):
    def decorator(*args, **kwargs):
        t = Thread(target = function, args=args, kwargs=kwargs)
        t.daemon = True
        t.start()
    return decorator
Run Code Online (Sandbox Code Playgroud)

所需用法:

@postpone
def foo():
    pass #do stuff
Run Code Online (Sandbox Code Playgroud)

tom*_*ell 64

我继续在规模和生产中使用这种实现,没有任何问题.

装饰者定义:

def start_new_thread(function):
    def decorator(*args, **kwargs):
        t = Thread(target = function, args=args, kwargs=kwargs)
        t.daemon = True
        t.start()
    return decorator
Run Code Online (Sandbox Code Playgroud)

用法示例:

@start_new_thread
def foo():
  #do stuff
Run Code Online (Sandbox Code Playgroud)

随着时间的推移,堆栈已经过更新和转换.

最初是Python 2.4.7,Django 1.4,Gunicorn 0.17.2,现在是Python 3.6,Django 2.1,Waitress 1.1.

如果您正在使用任何数据库事务,Django将创建一个新连接,这需要手动关闭:

from django.db import connection

@postpone
def foo():
  #do stuff
  connection.close()
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这将泄漏数据库连接,因为django将为每个线程创建一个新的数据库连接,并且您负责关闭它. (8认同)
  • 测试确认@Chronial是正确的。如果您的函数执行数据库事务(读取的是我测试的内容),那么将创建一个新的连接。然后线程终止连接剩余并在80 Postgres拒绝创建任何其他连接后 (2认同)
  • 当服务器关闭并且您推迟的功能未运行或正在运行时,它会被中止。您需要从主线程中调用新线程的`join`方法,但是没有一个好的方法。这是人们使用芹菜等的原因之一。 (2认同)

Gly*_*son 16

Celery是一个异步任务队列/作业队列.它有很好的文档记录,非常适合您的需求.我建议你从这里开始