9

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

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

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

谢谢!

4

4 回答 4

6

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

python manage.py runserver --noreload

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

于 2013-01-03T16:23:32.080 回答
3

我在我的项目中使用 Python 3.5 和 Django 1.8.5,最近遇到了类似的问题。我可以轻松地直接使用SIGNALxxx.py运行我的代码,但它不能作为一个包在 Django 上执行,因为错误“信号仅在主线程中有效”。

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

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

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

谢谢~

于 2016-01-20T02:31:56.937 回答
2

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

将您的注册调用放在 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)
于 2018-03-22T09:44:57.063 回答
0

尽管该问题并未准确描述您所处的情况,但这里有一些更通用的建议:

信号只发送到主线程。出于这个原因,信号处理程序应该在主线程中。从那时起,信号触发的动作需要传达给其他线程。我通常使用Events来做到这一点。信号处理程序设置事件,其他线程将读取该事件,然后意识到动作 X 已被触发。显然,这意味着应该在线程之间共享事件属性。

于 2012-01-06T09:14:18.210 回答