使用 pyinstaller 构建 .exe 后无法终止或终止子进程

Cannot terminate or kill subprocess after building .exe with pyinstaller

提问人:MasterOfDesaster42 提问时间:9/27/2023 最后编辑:MasterOfDesaster42 更新时间:9/28/2023 访问量:80

问:

在使用 python 执行脚本时,以我下面描述的方式终止以下子进程非常有效。但是,使用 pyinstaller 构建 .exe 文件后,blender 进程不会终止。

bpy_script_path = os.path.join(main_dir, 'Packages', 'Scripts', 'BlenderRendering', 'bpy_script.py')
blender_command = [blender_executable, '--background','--python', bpy_script_path]

if os.name == 'nt':
    CREATE_NO_WINDOW = 0x08000000
    blender_process = subprocess.Popen(blender_command, creationflags = CREATE_NO_WINDOW)
else:
    blender_process = subprocess.Popen(blender_command)
            
while blender_process.poll() == None:
    try:
        msg = queue.get_nowait()
        if msg[0] == 'kill':
            #tried first
            blender_process.kill()
            blender_process.wait()
            
            #tried second
            blender_process.terminate()
            blender_process.wait()

            #tried third
            subprocess.call(['taskkill', '/F', '/T', '/PID', str(blender_process.pid)])
            
            queue.put(('kill successful', None, None))
            return False
    except:
        pass
    time.sleep(1)

我提供的代码片段是作为多进程运行的脚本的一部分。因此,通过队列进行通信。我想在主应用程序关闭时终止/终止搅拌机进程。由于主应用程序在关闭时等待“kill successful”消息,因此无法终止 blender 进程会导致main_window在循环中运行,等待成功终止的消息。我也尝试使用 psutil,但这也不起作用。不知道此时该怎么做。.

while blender_process.poll() == None:
    msg = None
    try:
        msg = queue.get_nowait()
    except:
        pass
    if msg:
        if msg[0] == 'kill':
            subprocess.call(['taskkill', '/F', '/T', '/PID', str(blender_process.pid)])
            queue.put(('kill successful', None, None))
            return False
    time.sleep(1)
Python 多处理 子进程 终止

评论

0赞 Karo 9/27/2023
你们的操作系统是什么?是 Windows 吗?
0赞 MasterOfDesaster42 9/27/2023
是的,我使用的是 Windows,因此行:if os.name == 'nt':
0赞 AKX 9/27/2023
好吧,这会阻止您看到错误。可能想摆脱它。try: except: pass
0赞 Karo 9/27/2023
是的,正如@AKX所说,请删除它并考虑调试
0赞 Abdul Aziz Barkat 9/27/2023
我认为您的错误可能是因为您没有指定 stdin、stdout 和 stderr 并使用 noconsole 标志构建了 exe?如 AKX 所述,删除该 try-except 并查看或至少输出有关异常的信息。

答:

0赞 MasterOfDesaster42 9/28/2023 #1

问题中提到的所有三种解决方案都非常适合终止多进程。问题在于不同进程之间的沟通。由于多个进程在没有同步的情况下同时访问多处理队列,因此某些信号/消息未到达其假定的目的地。特别是在这种情况下,“kill”消息没有通过,因为主进程中的另一个循环检查队列已经收到消息。使用两个多处理事件(main_window_close 和 blender_terminated)解决了该问题,而不是依赖于也用于其他通信的同一队列:

while blender_process.poll() == None:
    if main_window_close.is_set():
        blender_process.terminate()
        blender_process.wait()
        blender_terminated.set()
        return False
    time.sleep(1)