我正在构建一个 django 应用程序,它依赖于一个已实现 SIGINT 信号处理程序的 python 模块。
假设我无法更改我所依赖的模块,我该如何解决“信号仅在主线程中有效”错误我将它集成到 Django 中?
我可以在 Django 主线程上运行它吗?有没有办法禁止处理程序允许模块在非主线程上运行?
谢谢!
我正在构建一个 django 应用程序,它依赖于一个已实现 SIGINT 信号处理程序的 python 模块。
假设我无法更改我所依赖的模块,我该如何解决“信号仅在主线程中有效”错误我将它集成到 Django 中?
我可以在 Django 主线程上运行它吗?有没有办法禁止处理程序允许模块在非主线程上运行?
谢谢!
Django 的内置开发服务器默认启用自动重新加载功能,它会生成一个新线程作为重新加载代码的一种方式。要解决这个问题,您可以简单地执行以下操作,尽管您显然会失去自动重新加载的便利:
python manage.py runserver --noreload
在选择生产设置时,您还需要注意这一点。至少某些部署选项(例如线程 fastcgi)肯定会在主线程之外执行您的代码。
我在我的项目中使用 Python 3.5 和 Django 1.8.5,最近遇到了类似的问题。我可以轻松地直接使用SIGNALxxx.py
运行我的代码,但它不能作为一个包在 Django 上执行,因为错误“信号仅在主线程中有效”。
首先,runserver with--noreload --nothreading
是可用的,但它运行我的多线程代码对我来说太慢了。
其次,我发现__init__.py
我的包中的代码在主线程中运行。但是,当然,只有主线程可以捕捉到这个信号,我的包中的代码根本捕捉不到它。它不能解决我的问题,但它可能是你的解决方案。
subprocess
最后,我发现有一个以Python命名的内置模块。这意味着你可以用它运行一个子真正的完整进程,也就是说,这个进程有自己的主线程,所以你可以在这里很容易地用SIGNAL运行你的代码。虽然我不知道使用它的性能,但它对我来说效果很好。PS,您可以subprocess
在 Python 文档中找到有关的所有详细信息。
谢谢~
有一种更简洁的方法,它不会破坏您使用线程和进程的能力。
将您的注册调用放在 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)
尽管该问题并未准确描述您所处的情况,但这里有一些更通用的建议:
信号只发送到主线程。出于这个原因,信号处理程序应该在主线程中。从那时起,信号触发的动作需要传达给其他线程。我通常使用Events来做到这一点。信号处理程序设置事件,其他线程将读取该事件,然后意识到动作 X 已被触发。显然,这意味着应该在线程之间共享事件属性。