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

问题描述 投票:0回答:1

使用 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)

我提供的代码片段是作为多进程运行的脚本的一部分。因此,通过队列进行通信。当主应用程序关闭时,我想终止/终止搅拌机进程。由于主应用程序在关闭时等待“终止成功”消息,因此无法终止搅拌机进程会导致 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 multiprocessing subprocess terminate
1个回答
0
投票

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

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)
© www.soinside.com 2019 - 2024. All rights reserved.