gpt4 book ai didi

python - 为什么不能从 Kivy 终止这个 Python 多进程?

转载 作者:太空狗 更新时间:2023-10-30 00:06:57 25 4
gpt4 key购买 nike

我正在尝试从 Kivy 应用程序中运行 django 开发服务器。到目前为止,这确实很有效。

现在我想允许用户在服务器运行时继续使用该程序。我的想法是为 httpd.serve_forever() 创建一个 multiprocessing.Process 以避免完全锁定主程序。做得很好。这是我的 internal_django 模块中的代码:

import multiprocessing
import os
import time

from wsgiref.simple_server import make_server

def django_wsgi_application():

PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
settings_module = "djangosettings"#%s.djangosettings" % PROJECT_ROOT.split(os.sep)[-1]

os.environ.update({"DJANGO_SETTINGS_MODULE":settings_module})

from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

return application


class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]


class DjangoServer():
__metaclass__ = Singleton

def start(self):
self.httpd = make_server('', 8000, django_wsgi_application())
self.server = multiprocessing.Process(target=self.httpd.serve_forever)
self.server.start()
print "Now serving on port 8000..."
print "Server Process PID = %s" %self.server.pid

def stop(self):
print("shutdown initiated")
print "Server Process PID = %s" %self.server.pid
while self.server.is_alive():
self.server.terminate()
print("Server should have shut down")
time.sleep(1)
print("Server is_alive: %s" %self.server.is_alive())
self.server.join()
print("server process joined")



if __name__ == "__main__":
server = DjangoServer()
server.start()
time.sleep(3)
server.stop()

当我运行这段代码时,一切都按预期工作。这是控制台中输出的内容:

Now serving on port 8000...
Server Process PID = 1406
shutdown initiated
Server Process PID = 1406
Server should have shut down
Server is_alive: False
server process joined

下一步是提供一种从 Kivy 应用程序中停止服务器的方法。为此,我只想像以前一样使用我的 DjangoServer 类:

from internal_django import DjangoServer

class StartScreen(Screen):
def start_server(self):
server = DjangoServer()
server.start()


class StopScreen(Screen):
def stop_server(self):
server = DjangoServer()
server.stop()

但是当这样做时,进程一旦启动就永远不会退出。我的第一个想法是 Singleton 没有按预期工作,我试图退出错误的进程。但正如您在输出中看到的那样,PID 是相同的。服务器收到终止命令,但继续工作。这是控制台的样子:

Now serving on port 8000...
Server Process PID = 1406
shutdown initiated
Server Process PID = 1406
Server should have shut down
Server should have shut down
Server should have shut down
Server should have shut down
Server should have shut down
Server should have shut down
Server should have shut down
Server should have shut down

(and so on, until i manually kill the server process)

我是否以完全错误的方式使用多处理? Kivy 是否以某种方式干扰了这个过程?

最佳答案

我认为这里的问题可能有两个:

  1. 信号处理程序正在拦截 Process.terminate() 发送的 TERM 请求并忽略它。要验证这一点,只需在新流程中使用 signal.getsignal(signal.SIGTERM) 并打印结果。要避免此类问题,您可以使用 signal.signal(signal.SIGTERM, signal.SIG_DFL) 重置默认行为,但请记住,SIGTERM 被框架静音可能是有原因的(我对 Django 也不熟悉也不与 Kivy 一起使用)。

  2. 如果您使用的是 Python 2,则必须考虑到如果解释器在线程库(锁、信号量等)的同步原语或 native C 调用上被阻塞,则解释器不会处理信号。 serve_forever() 函数可能会在这些情况下失败(使用源的力量!)。快速检查可能是尝试在 Python 3 上运行代码,看看它是否有效。

一个快速但肮脏的解决方案是等待一小段时间,如果进程仍然存在则发送一个 SIGKILL。

import os
import signal

process.terminate()
process.join(1)

if process.is_alive() and os.name != 'nt':
try:
os.kill(process.pid, signal.SIGKILL)
process.join()
except OSError:
return # process might have died while checking it

在 Windows 上,您无法以如此简单的方式终止进程,这就是我测试 os.name 的原因。

这是一种非常原始的方法,所以我宁愿建议找出问题的原因。

关于python - 为什么不能从 Kivy 终止这个 Python 多进程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26959371/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com