【问题标题】:Django Threading and TestsDjango 线程和测试
【发布时间】:2013-07-04 16:24:05
【问题描述】:

我有一个多线程 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 完成的。

有什么想法吗?

【问题讨论】:

  • 我已经更新了这个问题。是不是更清楚了?基本思想是,如果 bar() 在测试数据库中创建了一个对象,则它在第二个代码中不存在,但在第一个代码中。
  • 你应该检查你的假设。如果考虑到 Django 数据库连接的工作方式,在线程中创建多个项目比串行创建多个项目要快,我会非常感到惊讶。

标签: database django multithreading unit-testing


【解决方案1】:

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

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

正确的做法是:

  • 优化您的代码以更快地处理请求或
  • 使用 Celery 或 RQ 之类的任务系统将您的工作卸载到后台(这存在上述一些问题,但更直接)。

PS。不要尝试设置 Celery 或 RQ 进行测试。您应该只模拟任务并单独测试它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-29
    • 2015-03-21
    • 2021-12-04
    • 2017-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-05
    相关资源
    最近更新 更多