feat: 载入各种服务
This commit is contained in:
@@ -18,12 +18,6 @@
|
||||
|
||||
# Contact: DLmaster_361@163.com
|
||||
|
||||
"""
|
||||
AUTO_MAA
|
||||
AUTO_MAA图像组件
|
||||
v4.4
|
||||
作者:ClozyA
|
||||
"""
|
||||
|
||||
import base64
|
||||
import hashlib
|
||||
@@ -56,10 +50,8 @@ class ImageUtils:
|
||||
"""
|
||||
如果图片大于max_size_mb,则压缩并覆盖原文件,返回原始路径(Path对象)
|
||||
"""
|
||||
if hasattr(Image, "Resampling"): # Pillow 9.1.0及以后
|
||||
RESAMPLE = Image.Resampling.LANCZOS
|
||||
else:
|
||||
RESAMPLE = Image.ANTIALIAS
|
||||
|
||||
RESAMPLE = Image.Resampling.LANCZOS # Pillow 9.1.0及以后
|
||||
|
||||
max_size = max_size_mb * 1024 * 1024
|
||||
if image_path.stat().st_size <= max_size:
|
||||
@@ -70,7 +62,7 @@ class ImageUtils:
|
||||
quality = 90 if suffix in [".jpg", ".jpeg"] else None
|
||||
step = 5
|
||||
|
||||
if suffix in [".jpg", ".jpeg"]:
|
||||
if quality is not None:
|
||||
while True:
|
||||
img.save(image_path, quality=quality, optimize=True)
|
||||
if image_path.stat().st_size <= max_size or quality <= 10:
|
||||
|
||||
@@ -19,36 +19,33 @@
|
||||
# Contact: DLmaster_361@163.com
|
||||
|
||||
|
||||
import asyncio
|
||||
import psutil
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
from PySide6.QtCore import QTimer, QObject, Signal
|
||||
|
||||
|
||||
class ProcessManager(QObject):
|
||||
class ProcessManager:
|
||||
"""进程监视器类,用于跟踪主进程及其所有子进程的状态"""
|
||||
|
||||
processClosed = Signal()
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self.main_pid = None
|
||||
self.tracked_pids = set()
|
||||
self.check_task = None
|
||||
|
||||
self.check_timer = QTimer()
|
||||
self.check_timer.timeout.connect(self.check_processes)
|
||||
|
||||
def open_process(self, path: Path, args: list = [], tracking_time: int = 60) -> int:
|
||||
async def open_process(
|
||||
self, path: Path, args: list = [], tracking_time: int = 60
|
||||
) -> None:
|
||||
"""
|
||||
启动一个新进程并返回其pid,并开始监视该进程
|
||||
|
||||
:param path: 可执行文件的路径
|
||||
:param args: 启动参数列表
|
||||
:param tracking_time: 子进程追踪持续时间(秒)
|
||||
:return: 新进程的PID
|
||||
Parameters
|
||||
----------
|
||||
path: 可执行文件的路径
|
||||
args: 启动参数列表
|
||||
tracking_time: 子进程追踪持续时间(秒)
|
||||
"""
|
||||
|
||||
process = subprocess.Popen(
|
||||
@@ -60,9 +57,9 @@ class ProcessManager(QObject):
|
||||
stderr=subprocess.DEVNULL,
|
||||
)
|
||||
|
||||
self.start_monitoring(process.pid, tracking_time)
|
||||
await self.start_monitoring(process.pid, tracking_time)
|
||||
|
||||
def start_monitoring(self, pid: int, tracking_time: int = 60) -> None:
|
||||
async def start_monitoring(self, pid: int, tracking_time: int = 60) -> None:
|
||||
"""
|
||||
启动进程监视器,跟踪指定的主进程及其子进程
|
||||
|
||||
@@ -70,7 +67,7 @@ class ProcessManager(QObject):
|
||||
:param tracking_time: 子进程追踪持续时间(秒)
|
||||
"""
|
||||
|
||||
self.clear()
|
||||
await self.clear()
|
||||
|
||||
self.main_pid = pid
|
||||
self.tracking_time = tracking_time
|
||||
@@ -89,16 +86,16 @@ class ProcessManager(QObject):
|
||||
except psutil.NoSuchProcess:
|
||||
pass
|
||||
|
||||
# 启动持续追踪机制
|
||||
self.start_time = datetime.now()
|
||||
self.check_timer.start(100)
|
||||
# 启动持续追踪任务
|
||||
if tracking_time > 0:
|
||||
self.check_task = asyncio.create_task(self.track_processes())
|
||||
await asyncio.sleep(tracking_time)
|
||||
await self.stop_tracking()
|
||||
|
||||
def check_processes(self) -> None:
|
||||
"""检查跟踪的进程是否仍在运行,并更新子进程列表"""
|
||||
|
||||
# 仅在时限内持续更新跟踪的进程列表,发现新的子进程
|
||||
if (datetime.now() - self.start_time).total_seconds() < self.tracking_time:
|
||||
async def track_processes(self) -> None:
|
||||
"""更新子进程列表"""
|
||||
|
||||
while True:
|
||||
current_pids = set(self.tracked_pids)
|
||||
for pid in current_pids:
|
||||
try:
|
||||
@@ -109,12 +106,19 @@ class ProcessManager(QObject):
|
||||
self.tracked_pids.add(child.pid)
|
||||
except psutil.NoSuchProcess:
|
||||
continue
|
||||
await asyncio.sleep(0.1)
|
||||
|
||||
if not self.is_running():
|
||||
self.clear()
|
||||
self.processClosed.emit()
|
||||
async def stop_tracking(self) -> None:
|
||||
"""停止更新子进程列表"""
|
||||
|
||||
def is_running(self) -> bool:
|
||||
if self.check_task and not self.check_task.done():
|
||||
self.check_task.cancel()
|
||||
try:
|
||||
await self.check_task
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
|
||||
async def is_running(self) -> bool:
|
||||
"""检查所有跟踪的进程是否还在运行"""
|
||||
|
||||
for pid in self.tracked_pids:
|
||||
@@ -127,11 +131,9 @@ class ProcessManager(QObject):
|
||||
|
||||
return False
|
||||
|
||||
def kill(self, if_force: bool = False) -> None:
|
||||
async def kill(self, if_force: bool = False) -> None:
|
||||
"""停止监视器并中止所有跟踪的进程"""
|
||||
|
||||
self.check_timer.stop()
|
||||
|
||||
for pid in self.tracked_pids:
|
||||
try:
|
||||
proc = psutil.Process(pid)
|
||||
@@ -145,13 +147,11 @@ class ProcessManager(QObject):
|
||||
except psutil.NoSuchProcess:
|
||||
continue
|
||||
|
||||
if self.main_pid:
|
||||
self.processClosed.emit()
|
||||
self.clear()
|
||||
await self.clear()
|
||||
|
||||
def clear(self) -> None:
|
||||
async def clear(self) -> None:
|
||||
"""清空跟踪的进程列表"""
|
||||
|
||||
await self.stop_tracking()
|
||||
self.main_pid = None
|
||||
self.check_timer.stop()
|
||||
self.tracked_pids.clear()
|
||||
|
||||
@@ -25,6 +25,14 @@ __license__ = "GPL-3.0 license"
|
||||
|
||||
|
||||
from .logger import get_logger
|
||||
from .ImageUtils import ImageUtils
|
||||
from .ProcessManager import ProcessManager
|
||||
from .security import dpapi_encrypt, dpapi_decrypt
|
||||
|
||||
__all__ = ["get_logger", "dpapi_encrypt", "dpapi_decrypt"]
|
||||
__all__ = [
|
||||
"get_logger",
|
||||
"ImageUtils",
|
||||
"ProcessManager",
|
||||
"dpapi_encrypt",
|
||||
"dpapi_decrypt",
|
||||
]
|
||||
|
||||
@@ -59,6 +59,7 @@ _logger = _logger.patch(lambda record: record["extra"].setdefault("module", "未
|
||||
def get_logger(module_name: str):
|
||||
"""
|
||||
获取一个绑定 module 名的日志器
|
||||
|
||||
:param module_name: 模块名称,如 "用户管理"
|
||||
:return: 绑定后的 logger
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user