Python:Django:信号处理程序和主线程

时间:2011-12-20 08:51:18

标签: python django multithreading signal-handling

我正在构建一个django应用程序,它依赖于一个已经实现了SIGINT信号处理程序的python模块。

假设我无法更改我所依赖的模块,我如何解决“信号只能在主线程中工作”错误我将它集成到Django中?

我可以在Django主线程上运行吗? 有没有办法禁止处理程序允许模块在非主线程上运行?

谢谢!

4 个答案:

答案 0 :(得分:3)

Django的内置开发服务器默认启用了自动重新加载功能,它生成一个新线程作为重新加载代码的方法。要解决这个问题,您可以简单地执行以下操作,尽管您显然会失去自动重新加载的便利性:

python manage.py runserver --noreload

在选择生产设置时,您还需要注意这一点。至少有一些部署选项(例如线程fastcgi)肯定会在主线程外执行你的代码。

答案 1 :(得分:1)

我在项目中使用Python 3.5和Django 1.8.5,最近我遇到了类似的问题。我可以直接使用 SIGNAL 轻松运行我的xxx.py代码,但由于错误“信号仅在主线程中有效<,因此无法在Django上执行/强>”。

首先,带有--noreload --nothreading的runserver是可用的,但它对我来说运行我的多线程代码太慢了。

其次,我发现我的包的__init__.py中的代码在主线程中运行。但是,当然,只有主线程可以捕获这个信号,我的包中的代码根本无法捕获它。它无法解决我的问题,但它可能是一个解决方案。

最后,我发现Python中有一个名为subprocess的内置模块。这意味着您可以使用它运行子实际的完整流程,也就是说,此流程有自己的主线程,因此您可以在此处轻松地使用 SIGNAL 运行代码。虽然我不知道使用它的性能,但对我来说效果很好。 PS,您可以在Python文档中找到有关subprocess的所有详细信息。

谢谢〜

答案 2 :(得分:1)

有一种更简洁的方法,它不会破坏您使用线程和进程的能力。

将您的注册电话放入manage.py:

def handleKill(signum, frame):
    print "Killing Thread."
    # Or whatever code you want here
    ForceTerminate.FORCE_TERMINATE = True 
    print threading.active_count()
    exit(0)


if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")

from django.core.management import execute_from_command_line

signal.signal(signal.SIGINT, handleKill)
signal.signal(signal.SIGTERM, handleKill)

execute_from_command_line(sys.argv)

答案 3 :(得分:0)

虽然问题并没有准确描述你所处的情况,但这里有一些更通用的建议:

信号仅发送到主线程。因此,信号处理程序应位于主线程中。 从那时起,信号触发的动作需要传递给其他线程。我通常使用Events执行此操作。信号处理程序设置事件,其他线程将读取该事件,然后意识到已触发操作X.显然,这意味着应该在线程之间共享事件属性。