Django线程和测试

时间:2013-07-06 23:24:16

标签: database django multithreading unit-testing

我有一个多线程的django应用程序,它可以在不同的线程中创建一些对象,以便更快地返回。创建的对象仅用于跟踪用户所做的事情,并且不会对时间敏感。

视图函数看起来像这样:

def foo(request):
    #... do important computation...
    bar(x, y, z)
    return HttpResponse()

这里的一切都很好,但是当我把它改成这样并使用线程时:

def foo(request):
    #... do important computation...
    thread = Thread(target=bar, args=(x, y, z))
    thread.start()
    if testing_mode:
        thread.join()
    return HttpResponse()

第二个版本失败。这都是使用TransactionTestCase和mySQL完成的。

有什么想法吗?

1 个答案:

答案 0 :(得分:5)

使用线程来卸载请求并不是一个好主意。有许多陷阱,并没有什么好处。主要问题(以及您的问题与这些问题有关)是:

  • Django中的每个线程都使用单独的数据库连接,因此:
    • 你失去了交易的好处
    • 您必须在线程中手动关闭连接
    • 如果你没有以正确的方式关闭线程中的连接(并且很难做到正确),那么你将有数百个与数据库的开放连接,这会给你带来问题
    • 你有测试问题,因为测试框架在数据库连接上做了一些技巧,而且在线程连接时无法做到这一点
  • 翻译框架在线程中不起作用
  • 如果wsgi服务器决定重新加载,你的线程可能会被过早杀死,但没有请求处理
  • Django错误处理对线程不起作用

正确的方法是:

  • 优化代码以更快地提供请求或
  • 使用像Celery或RQ这样的任务系统将您的工作卸载到后台(这有一些上面的问题,但更直接)。

PS。不要尝试为测试设置Celery或RQ。你应该模拟任务并单独测试它。