我正在构建一个django应用程序,它依赖于一个已经实现了SIGINT信号处理程序的python模块。
假设我无法更改我所依赖的模块,我如何解决“信号只能在主线程中工作”错误我将它集成到Django中?
我可以在Django主线程上运行吗? 有没有办法禁止处理程序允许模块在非主线程上运行?
谢谢!
答案 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.显然,这意味着应该在线程之间共享事件属性。