Files
video-subtitle-remover/backend/tools/process_manager.py
Jason f78e985e1c 使用PySide6-Fluent-Widgets重构整套UI
添加任务列表组件并优化视频加载逻辑
支持可视化显示字幕区域
整理所有模型, 分别为STTN智能擦除, STTN字幕检测, LAMA, ProPainter, OpenCV
提高处理性能
新增CPU运行模式并优化多语言支持
修复Propainter模式部分视频报错

本次提交新增了CPU运行模式,适用于无GPU加速的场景。同时,优化了多语言支持,新增了日语、韩语、越南语等语言配置文件,并更新了README文档以反映新的运行模式和多语言支持。此外,修复了部分代码逻辑,提升了系统的稳定性和兼容性。
2025-05-22 08:41:59 +08:00

128 lines
4.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""
@desc: 进程管理器,用于管理和终止子进程
"""
import weakref
import signal
import os
import platform
import logging
import atexit
import subprocess
import concurrent.futures
class ProcessManager:
"""
进程管理器类,用于管理子进程的生命周期
使用弱引用避免内存泄漏
"""
_instance = None
@classmethod
def instance(cls):
"""单例模式获取实例"""
if cls._instance is None:
cls._instance = ProcessManager()
return cls._instance
def __init__(self):
"""初始化进程管理器"""
self.processes = {}
self.logger = logging.getLogger(__name__)
# 注册退出处理函数
atexit.register(self.terminate_all)
def add_process(self, process, name=None):
"""
添加进程到管理器
Args:
process: 要添加的进程对象 (subprocess.Popen实例)
name: 进程名称如果不提供则使用进程ID
"""
if process is None:
return
process_id = name or f"Process:{id(process)}"
self.processes[process_id] = process
print(f"Added process: {process_id}, PID: {process.pid if hasattr(process, 'pid') else 'unknown'}")
return process_id
def add_pid(self, pid, name=None):
process_id = name or f"Pid:{pid}"
self.processes[process_id] = pid
print(f"Added process: {process_id}, PID: {pid}")
return process_id
def remove_process(self, process_id):
"""
从管理器中移除进程
Args:
process_id: 进程ID或名称
"""
if process_id in self.processes:
del self.processes[process_id]
print(f"Removed process: {process_id}")
return True
return False
def terminate_all(self):
"""并发终止所有管理的进程"""
with concurrent.futures.ThreadPoolExecutor() as executor:
futures = []
for process_id, process in list(self.processes.items()):
if isinstance(process, int):
futures.append(executor.submit(self.terminate_by_pid, process))
else:
futures.append(executor.submit(self.terminate_by_process, process))
# 等待所有终止操作完成
concurrent.futures.wait(futures)
# 清空进程字典
self.processes.clear()
def terminate_by_process(self, process):
if process is None:
return
try:
print(f"Terminating process: pid: {process.pid}")
if hasattr(process, 'poll') and process.poll() is not None:
# 进程已经结束,直接返回
return
# 进程还在运行
process.terminate()
if hasattr(process, 'join'):
try:
process.join(timeout=3)
except:
pass
if hasattr(process, 'wait'):
try:
process.wait(timeout=3)
except:
pass
# 进程未能正常终止,尝试强制终止
if hasattr(process, 'kill'):
process.kill()
except Exception as e:
# print(f"Error terminating process: {str(e)}")
pass
self.terminate_by_pid(process.pid)
def terminate_by_pid(self, pid):
try:
# 使用系统命令强制终止进程
if platform.system() == 'Windows':
subprocess.run(['taskkill', '/F', '/T', '/PID', str(pid)],
stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=3)
else:
subprocess.run(['pkill', '-9', '-P', str(pid)],
stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=2)
subprocess.run(['kill', '-9', str(pid)],
stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=3)
except Exception as e:
print(f"Error forcibly terminating process with PID {pid}: {str(e)}")