bug修复
This commit is contained in:
1 parent
9d15bdd3c3
commit
df797bc906
2 files changed
+151
-10
No files matched your search
@@ -6,7 +6,10 @@ a = Analysis(
|
|||||||
['main.py'],
|
['main.py'],
|
||||||
pathex=[],
|
pathex=[],
|
||||||
binaries=[],
|
binaries=[],
|
||||||
datas=[],
|
datas=[
|
||||||
|
# 将 small_machine_transform.py 作为数据文件包含,以便 Blender 可以调用
|
||||||
|
('utils/small_machine_transform.py', 'utils'),
|
||||||
|
],
|
||||||
hiddenimports=[
|
hiddenimports=[
|
||||||
'redis',
|
'redis',
|
||||||
'oss2',
|
'oss2',
|
||||||
@@ -39,7 +42,7 @@ exe = EXE(
|
|||||||
[],
|
[],
|
||||||
name='factory_sliceing',
|
name='factory_sliceing',
|
||||||
debug=False,
|
debug=False,
|
||||||
bootloader_ignore_signals=False,
|
bootloader_ignore_signals=False, # 允许信号传播,使 Ctrl+C 可以中断
|
||||||
strip=False,
|
strip=False,
|
||||||
upx=True,
|
upx=True,
|
||||||
upx_exclude=[],
|
upx_exclude=[],
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import shutil
|
|||||||
import json
|
import json
|
||||||
import shlex
|
import shlex
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import signal
|
||||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||||
from .oss_redis import ossClient
|
from .oss_redis import ossClient
|
||||||
from .logs import log
|
from .logs import log
|
||||||
@@ -21,6 +23,75 @@ elif ENV == 'prod':
|
|||||||
url = 'https://mp.api.suwa3d.com'
|
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 获取下载目录
|
# 根据打印ID 获取下载目录
|
||||||
def getDownloadDirByPrintId(printIds):
|
def getDownloadDirByPrintId(printIds):
|
||||||
# 调用接口获取下载的路径
|
# 调用接口获取下载的路径
|
||||||
@@ -317,9 +388,8 @@ def _process_single_item(v, arrDownloadPath, dirNewName, dirPath, isSmallMachine
|
|||||||
|
|
||||||
# 通过blender 调用执行 python 文件
|
# 通过blender 调用执行 python 文件
|
||||||
blender_bin_path = findBpyModule()
|
blender_bin_path = findBpyModule()
|
||||||
# 获取 small_machine_transform.py 的绝对路径
|
# 获取 small_machine_transform.py 的绝对路径(兼容打包环境)
|
||||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
transform_script_path = get_transform_script_path()
|
||||||
transform_script_path = os.path.join(script_dir, 'small_machine_transform.py')
|
|
||||||
|
|
||||||
# 将 homo_matrix 转换为 JSON 字符串
|
# 将 homo_matrix 转换为 JSON 字符串
|
||||||
homo_matrix_json = json.dumps(homo_matrix)
|
homo_matrix_json = json.dumps(homo_matrix)
|
||||||
@@ -358,17 +428,85 @@ def _process_single_item(v, arrDownloadPath, dirNewName, dirPath, isSmallMachine
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
log(f"开始执行 Blender 转换命令...")
|
log(f"开始执行 Blender 转换命令...")
|
||||||
# 使用 subprocess 执行命令,捕获输出和错误
|
# 使用 subprocess.Popen 以便更好地控制进程和信号处理
|
||||||
# 在 Windows 上,Blender 输出可能是 UTF-8,需要指定编码并处理错误
|
# 在 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,
|
cmd,
|
||||||
capture_output=True,
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
text=True,
|
text=True,
|
||||||
encoding='utf-8', # 指定 UTF-8 编码
|
encoding='utf-8', # 指定 UTF-8 编码
|
||||||
errors='replace', # 遇到无法解码的字符时替换为占位符,而不是抛出异常
|
errors='replace', # 遇到无法解码的字符时替换为占位符,而不是抛出异常
|
||||||
timeout=300, # 5分钟超时
|
startupinfo=startupinfo,
|
||||||
check=False # 不自动抛出异常,手动检查返回码
|
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}")
|
log(f"Blender 命令执行完成, 返回码: {result.returncode}")
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user