bug修复
This commit is contained in:
1 parent
9d15bdd3c3
commit
df797bc906
2 files changed
+151
-10
No files matched your search
@@ -6,6 +6,8 @@ import shutil
|
||||
import json
|
||||
import shlex
|
||||
import subprocess
|
||||
import sys
|
||||
import signal
|
||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||
from .oss_redis import ossClient
|
||||
from .logs import log
|
||||
@@ -21,6 +23,75 @@ elif ENV == 'prod':
|
||||
url = 'https://mp.api.suwa3d.com'
|
||||
|
||||
|
||||
def get_resource_path(relative_path):
|
||||
"""
|
||||
获取资源文件的绝对路径,兼容 PyInstaller 打包后的环境
|
||||
参数:
|
||||
relative_path: 相对于脚本目录的相对路径
|
||||
返回:
|
||||
资源文件的绝对路径
|
||||
"""
|
||||
try:
|
||||
# PyInstaller 创建临时文件夹,并将路径存储在 _MEIPASS 中
|
||||
base_path = sys._MEIPASS
|
||||
except AttributeError:
|
||||
# 如果不是打包环境,使用脚本所在目录
|
||||
base_path = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
return os.path.join(base_path, relative_path)
|
||||
|
||||
|
||||
def get_transform_script_path():
|
||||
"""
|
||||
获取 small_machine_transform.py 脚本的路径
|
||||
在打包成exe后,如果脚本不在可访问位置,则将其提取到临时目录
|
||||
返回:
|
||||
transform_script_path: 脚本的绝对路径
|
||||
"""
|
||||
# 首先尝试从资源路径获取
|
||||
if getattr(sys, 'frozen', False):
|
||||
# 打包后的环境
|
||||
# 尝试从资源路径获取
|
||||
resource_path = get_resource_path('utils/small_machine_transform.py')
|
||||
|
||||
# 如果资源路径存在,直接使用
|
||||
if os.path.exists(resource_path):
|
||||
return resource_path
|
||||
|
||||
# 如果不存在,尝试提取到临时目录
|
||||
import tempfile
|
||||
temp_dir = tempfile.gettempdir()
|
||||
extract_path = os.path.join(temp_dir, 'factory_sliceing_utils', 'small_machine_transform.py')
|
||||
|
||||
# 确保目录存在
|
||||
os.makedirs(os.path.dirname(extract_path), exist_ok=True)
|
||||
|
||||
# 如果提取路径不存在,尝试从资源中复制
|
||||
if not os.path.exists(extract_path):
|
||||
# 尝试从多个可能的资源路径查找
|
||||
possible_paths = [
|
||||
get_resource_path('small_machine_transform.py'),
|
||||
get_resource_path('utils/small_machine_transform.py'),
|
||||
]
|
||||
|
||||
for src_path in possible_paths:
|
||||
if os.path.exists(src_path):
|
||||
shutil.copy2(src_path, extract_path)
|
||||
log(f"已将 small_machine_transform.py 提取到: {extract_path}")
|
||||
return extract_path
|
||||
|
||||
# 如果提取路径存在,直接使用
|
||||
if os.path.exists(extract_path):
|
||||
return extract_path
|
||||
|
||||
# 如果都找不到,返回资源路径(即使不存在,让调用者处理错误)
|
||||
return resource_path
|
||||
else:
|
||||
# 开发环境,直接使用相对路径
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
return os.path.join(script_dir, 'small_machine_transform.py')
|
||||
|
||||
|
||||
# 根据打印ID 获取下载目录
|
||||
def getDownloadDirByPrintId(printIds):
|
||||
# 调用接口获取下载的路径
|
||||
@@ -317,9 +388,8 @@ def _process_single_item(v, arrDownloadPath, dirNewName, dirPath, isSmallMachine
|
||||
|
||||
# 通过blender 调用执行 python 文件
|
||||
blender_bin_path = findBpyModule()
|
||||
# 获取 small_machine_transform.py 的绝对路径
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
transform_script_path = os.path.join(script_dir, 'small_machine_transform.py')
|
||||
# 获取 small_machine_transform.py 的绝对路径(兼容打包环境)
|
||||
transform_script_path = get_transform_script_path()
|
||||
|
||||
# 将 homo_matrix 转换为 JSON 字符串
|
||||
homo_matrix_json = json.dumps(homo_matrix)
|
||||
@@ -358,17 +428,85 @@ def _process_single_item(v, arrDownloadPath, dirNewName, dirPath, isSmallMachine
|
||||
|
||||
try:
|
||||
log(f"开始执行 Blender 转换命令...")
|
||||
# 使用 subprocess 执行命令,捕获输出和错误
|
||||
# 使用 subprocess.Popen 以便更好地控制进程和信号处理
|
||||
# 在 Windows 上,Blender 输出可能是 UTF-8,需要指定编码并处理错误
|
||||
result = subprocess.run(
|
||||
# 准备进程启动参数
|
||||
startupinfo = None
|
||||
preexec_fn = None
|
||||
if platform.system() == 'Windows':
|
||||
# Windows 上,不设置 CREATE_NEW_PROCESS_GROUP,以便 Ctrl+C 可以传播
|
||||
import subprocess as sp
|
||||
startupinfo = sp.STARTUPINFO()
|
||||
startupinfo.dwFlags |= sp.STARTF_USESHOWWINDOW
|
||||
startupinfo.wShowWindow = sp.SW_HIDE
|
||||
else:
|
||||
# Unix 系统,设置 preexec_fn 以确保信号处理正确
|
||||
preexec_fn = os.setsid
|
||||
|
||||
process = subprocess.Popen(
|
||||
cmd,
|
||||
capture_output=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
text=True,
|
||||
encoding='utf-8', # 指定 UTF-8 编码
|
||||
errors='replace', # 遇到无法解码的字符时替换为占位符,而不是抛出异常
|
||||
timeout=300, # 5分钟超时
|
||||
check=False # 不自动抛出异常,手动检查返回码
|
||||
startupinfo=startupinfo,
|
||||
preexec_fn=preexec_fn
|
||||
)
|
||||
|
||||
try:
|
||||
# 等待进程完成,捕获输出
|
||||
stdout, stderr = process.communicate(timeout=300) # 5分钟超时
|
||||
returncode = process.returncode
|
||||
except subprocess.TimeoutExpired:
|
||||
# 超时,终止进程
|
||||
log(f"Blender 命令执行超时,正在终止进程...")
|
||||
if platform.system() == 'Windows':
|
||||
process.terminate()
|
||||
try:
|
||||
process.wait(timeout=5)
|
||||
except subprocess.TimeoutExpired:
|
||||
process.kill()
|
||||
else:
|
||||
# Unix 系统,发送 SIGTERM 到进程组
|
||||
try:
|
||||
os.killpg(os.getpgid(process.pid), signal.SIGTERM)
|
||||
process.wait(timeout=5)
|
||||
except (subprocess.TimeoutExpired, ProcessLookupError, OSError):
|
||||
try:
|
||||
os.killpg(os.getpgid(process.pid), signal.SIGKILL)
|
||||
except (ProcessLookupError, OSError):
|
||||
pass
|
||||
raise
|
||||
except KeyboardInterrupt:
|
||||
# 收到中断信号,终止进程
|
||||
log(f"收到中断信号,正在终止 Blender 进程...")
|
||||
if platform.system() == 'Windows':
|
||||
process.terminate()
|
||||
try:
|
||||
process.wait(timeout=5)
|
||||
except subprocess.TimeoutExpired:
|
||||
process.kill()
|
||||
else:
|
||||
# Unix 系统,发送 SIGTERM 到进程组
|
||||
try:
|
||||
os.killpg(os.getpgid(process.pid), signal.SIGTERM)
|
||||
process.wait(timeout=5)
|
||||
except (subprocess.TimeoutExpired, ProcessLookupError, OSError):
|
||||
try:
|
||||
os.killpg(os.getpgid(process.pid), signal.SIGKILL)
|
||||
except (ProcessLookupError, OSError):
|
||||
pass
|
||||
raise # 重新抛出,让调用者处理
|
||||
|
||||
# 创建结果对象(模拟 subprocess.run 的返回值)
|
||||
class Result:
|
||||
def __init__(self, returncode, stdout, stderr):
|
||||
self.returncode = returncode
|
||||
self.stdout = stdout
|
||||
self.stderr = stderr
|
||||
|
||||
result = Result(returncode, stdout, stderr)
|
||||
|
||||
log(f"Blender 命令执行完成, 返回码: {result.returncode}")
|
||||
|
||||
|
||||
Reference in new issue
Block a user