Python: Django: 信号处理器与主线程
我正在开发一个Django应用,这个应用依赖于一个Python模块,而这个模块里实现了一个SIGINT信号处理器。
假设我不能修改我依赖的这个模块,我该如何解决在Django中集成时出现的“信号只能在主线程中工作”的错误呢?
我可以在Django的主线程中运行它吗?有没有办法禁用这个处理器,让模块可以在非主线程中运行呢?
谢谢!
4 个回答
有一种更简单的方法,这样做不会影响你使用线程和进程的能力。
把你的注册调用放在 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)
我在项目中使用的是Python 3.5和Django 1.8.5,最近遇到了一个类似的问题。我可以直接用SIGNAL轻松运行我的xxx.py
代码,但在Django中作为一个包运行时却出现了“signal only works in main thread”的错误,导致无法执行。
首先,使用--noreload --nothreading
启动服务器是可行的,但这样运行我的多线程代码速度太慢了。
其次,我发现我包中的__init__.py
代码是在主线程中运行的。当然,只有主线程才能捕获这个signal,所以我包里的代码根本无法捕获到。虽然这对我来说不能解决问题,但可能对你有帮助。
最后,我发现Python里有一个内置模块叫subprocess
。这个模块的意思是你可以用它来运行一个完整的子进程,也就是说,这个进程有自己的主线程,所以你可以在这里轻松运行带有SIGNAL的代码。虽然我不太清楚使用它的性能如何,但对我来说效果很好。顺便说一下,你可以在Python文档中找到关于subprocess
的所有详细信息。
谢谢~
Django自带的开发服务器默认开启了自动重载功能,这个功能会启动一个新的线程来重新加载代码。如果你想绕过这个功能,可以简单地做以下操作,不过这样的话你就失去了自动重载的便利:
python manage.py runserver --noreload
在选择你的生产环境设置时,你也需要注意这一点。至少有一些部署选项(比如线程型的fastcgi)会确保你的代码在主线程之外执行。