Refactor main.py to enable API call for updating slice status and enhance argument parsing. Update funcs.py for improved code readability and error handling in Blender execution.
This commit is contained in:
1 parent
7ea8b2d199
commit
d43a50e14d
2 files changed
+99
-32
No files matched your search
@@ -3,6 +3,7 @@ import redis
|
|||||||
import oss2,time,sys
|
import oss2,time,sys
|
||||||
import requests
|
import requests
|
||||||
import argparse,json
|
import argparse,json
|
||||||
|
from utils.funcs import requestApiToUpdateSliceStatus
|
||||||
|
|
||||||
# 将当前脚本所在目录添加到 Python 路径,以便导入 utils 模块
|
# 将当前脚本所在目录添加到 Python 路径,以便导入 utils 模块
|
||||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||||
@@ -50,14 +51,14 @@ def step1(versionId):
|
|||||||
objCounts += 1
|
objCounts += 1
|
||||||
|
|
||||||
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} 下载处理完成的obj文件数量: {objCounts}')
|
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} 下载处理完成的obj文件数量: {objCounts}')
|
||||||
# requestApiToUpdateSliceStatus(versionId,objCounts)
|
requestApiToUpdateSliceStatus(versionId,objCounts)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 读取 队列中一个数据出来
|
# 读取 队列中一个数据出来
|
||||||
def main(work_dir=None):
|
def main(work_dir=None):
|
||||||
|
|
||||||
|
global currentDir
|
||||||
# 如果指定了工作目录,使用指定的目录
|
# 如果指定了工作目录,使用指定的目录
|
||||||
if work_dir:
|
if work_dir:
|
||||||
work_dir = os.path.abspath(work_dir)
|
work_dir = os.path.abspath(work_dir)
|
||||||
@@ -122,13 +123,13 @@ def testMain():
|
|||||||
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} 处理完成,res={res}')
|
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} 处理完成,res={res}')
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
testMain()
|
#testMain()
|
||||||
# parser = argparse.ArgumentParser(description='排版打印订单处理程序')
|
parser = argparse.ArgumentParser(description='排版打印订单处理程序')
|
||||||
# parser.add_argument(
|
parser.add_argument(
|
||||||
# '--work-dir',
|
'--work-dir',
|
||||||
# type=str,
|
type=str,
|
||||||
# default=None,
|
default=None,
|
||||||
# help='指定工作目录(磁盘路径),例如: D:/work 或 /Users/username/work。如果不指定,则使用脚本所在目录'
|
help='指定工作目录(磁盘路径),例如: D:/work 或 /Users/username/work。如果不指定,则使用脚本所在目录'
|
||||||
# )
|
)
|
||||||
# args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
# main(work_dir=args.work_dir)
|
main(work_dir=args.work_dir)
|
||||||
@@ -1,14 +1,18 @@
|
|||||||
import requests,time
|
import requests
|
||||||
import os,platform
|
import time
|
||||||
|
import os
|
||||||
|
import platform
|
||||||
import shutil
|
import shutil
|
||||||
import json
|
import json
|
||||||
import shlex
|
import shlex
|
||||||
|
import subprocess
|
||||||
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
|
||||||
from .oss_func import download_file_with_check, checkFileExists
|
from .oss_func import download_file_with_check, checkFileExists
|
||||||
from .changeFiles import changeObjFile, changeMtlFile
|
from .changeFiles import changeObjFile, changeMtlFile
|
||||||
from .small_machine_transform import transform_save
|
from .small_machine_transform import transform_save
|
||||||
|
|
||||||
ENV = 'prod'
|
ENV = 'prod'
|
||||||
url = 'https://mp.api.suwa3d.com'
|
url = 'https://mp.api.suwa3d.com'
|
||||||
if ENV == 'dev':
|
if ENV == 'dev':
|
||||||
@@ -29,6 +33,7 @@ def getDownloadDirByPrintId(printIds):
|
|||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
# 根据批次id,进行切片中的状态变更
|
# 根据批次id,进行切片中的状态变更
|
||||||
def requestApiToUpdateSliceStatus(versionId, downloadCounts):
|
def requestApiToUpdateSliceStatus(versionId, downloadCounts):
|
||||||
api_url = f"{url}/api/printTypeSettingOrder/updateBatchSliceing?batch_id={versionId}&download_counts=" + str(downloadCounts)
|
api_url = f"{url}/api/printTypeSettingOrder/updateBatchSliceing?batch_id={versionId}&download_counts=" + str(downloadCounts)
|
||||||
@@ -48,6 +53,7 @@ def requestApiToUpdateSliceStatus(versionId,downloadCounts):
|
|||||||
log(f'状态变更请求异常, error={str(e)}')
|
log(f'状态变更请求异常, error={str(e)}')
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
# 判断是否上传了 JSON 文件
|
# 判断是否上传了 JSON 文件
|
||||||
def checkJsonFileExists(versionId):
|
def checkJsonFileExists(versionId):
|
||||||
log(f"检测文件和图片是否存在, versionId={versionId}")
|
log(f"检测文件和图片是否存在, versionId={versionId}")
|
||||||
@@ -59,7 +65,6 @@ def checkJsonFileExists(versionId):
|
|||||||
log(f'JSON文件不存在: {jsonFilePath}')
|
log(f'JSON文件不存在: {jsonFilePath}')
|
||||||
return False, False
|
return False, False
|
||||||
|
|
||||||
|
|
||||||
if not ossClient().object_exists(jpgFilePath):
|
if not ossClient().object_exists(jpgFilePath):
|
||||||
log(f'JPG文件不存在: {jpgFilePath}')
|
log(f'JPG文件不存在: {jpgFilePath}')
|
||||||
return False, False
|
return False, False
|
||||||
@@ -67,19 +72,20 @@ def checkJsonFileExists(versionId):
|
|||||||
return jsonFilePath, jpgFilePath
|
return jsonFilePath, jpgFilePath
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 检测本地文件是否存在
|
# 检测本地文件是否存在
|
||||||
def checkLocalFileExists(localFilePath):
|
def checkLocalFileExists(localFilePath):
|
||||||
if not os.path.exists(localFilePath):
|
if not os.path.exists(localFilePath):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
# 读取JSON文件内容
|
# 读取JSON文件内容
|
||||||
def readJsonFile(localFilePath):
|
def readJsonFile(localFilePath):
|
||||||
with open(localFilePath, 'r', encoding='utf-8') as f:
|
with open(localFilePath, 'r', encoding='utf-8') as f:
|
||||||
jsonData = json.load(f)
|
jsonData = json.load(f)
|
||||||
return jsonData
|
return jsonData
|
||||||
|
|
||||||
|
|
||||||
# 根据批次ID,获取批次信息
|
# 根据批次ID,获取批次信息
|
||||||
def getBatchInfo(versionId):
|
def getBatchInfo(versionId):
|
||||||
url1 = f"{url}/api/printTypeSettingOrder/getBatchInfoAndPrintMachineInfoByBatchId?batch_id={versionId}"
|
url1 = f"{url}/api/printTypeSettingOrder/getBatchInfoAndPrintMachineInfoByBatchId?batch_id={versionId}"
|
||||||
@@ -91,6 +97,7 @@ def getBatchInfo(versionId):
|
|||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
# 下载文件,读取文件内容,并且文件迁移至正确的目录里,不再放在临时目录里
|
# 下载文件,读取文件内容,并且文件迁移至正确的目录里,不再放在临时目录里
|
||||||
def downloadJsonAndJpgFileAndMoveToCorrectDir(versionId, currentDir):
|
def downloadJsonAndJpgFileAndMoveToCorrectDir(versionId, currentDir):
|
||||||
jsonFilePath, jpgFilePath = checkJsonFileExists(versionId)
|
jsonFilePath, jpgFilePath = checkJsonFileExists(versionId)
|
||||||
@@ -139,7 +146,6 @@ def downloadJsonAndJpgFileAndMoveToCorrectDir(versionId,currentDir):
|
|||||||
if not os.path.exists(jsonSubDir):
|
if not os.path.exists(jsonSubDir):
|
||||||
os.makedirs(jsonSubDir)
|
os.makedirs(jsonSubDir)
|
||||||
|
|
||||||
|
|
||||||
# 将数据移动过来
|
# 将数据移动过来
|
||||||
shutil.move(localFilePath, os.path.join(jsonSubDir, '3DPrintLayout.json'))
|
shutil.move(localFilePath, os.path.join(jsonSubDir, '3DPrintLayout.json'))
|
||||||
shutil.move(localJpgFilePath, os.path.join(jsonSubDir, f'{versionId}.jpg'))
|
shutil.move(localJpgFilePath, os.path.join(jsonSubDir, f'{versionId}.jpg'))
|
||||||
@@ -186,8 +192,6 @@ def getJsonData(dirNewName):
|
|||||||
log(f"数据不完整, orderId={orderId}, pid={pid}, printId={printId}, size={size}, counts={counts}")
|
log(f"数据不完整, orderId={orderId}, pid={pid}, printId={printId}, size={size}, counts={counts}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 创建数据结构
|
# 创建数据结构
|
||||||
modelInfo = {
|
modelInfo = {
|
||||||
"orderId": orderId,
|
"orderId": orderId,
|
||||||
@@ -277,6 +281,7 @@ def _process_single_item(v, arrDownloadPath, dirNewName, dirPath, isSmallMachine
|
|||||||
beginTime = time.time()
|
beginTime = time.time()
|
||||||
objsLocal = ""
|
objsLocal = ""
|
||||||
for objFiles in arrDownloadFiles:
|
for objFiles in arrDownloadFiles:
|
||||||
|
downloadBeginTime = time.time()
|
||||||
# 判断 mtl 和 jpg 文件是否存在,存在就不在下载了
|
# 判断 mtl 和 jpg 文件是否存在,存在就不在下载了
|
||||||
if "mtl" in objFiles["localPath"] or "jpg" in objFiles["localPath"]:
|
if "mtl" in objFiles["localPath"] or "jpg" in objFiles["localPath"]:
|
||||||
if os.path.exists(objFiles["localPath"]):
|
if os.path.exists(objFiles["localPath"]):
|
||||||
@@ -288,11 +293,13 @@ def _process_single_item(v, arrDownloadPath, dirNewName, dirPath, isSmallMachine
|
|||||||
log(error_msg)
|
log(error_msg)
|
||||||
return False, error_msg
|
return False, error_msg
|
||||||
|
|
||||||
|
log(f"下载文件耗时: {time.time() - downloadBeginTime}秒 - {objFiles['localPath']}")
|
||||||
# 下载成功之后要修改文件之间的关联路径
|
# 下载成功之后要修改文件之间的关联路径
|
||||||
if objFiles["localPath"].endswith(".obj"):
|
if objFiles["localPath"].endswith(".obj"):
|
||||||
|
beginChangeTime = time.time()
|
||||||
objsLocal = objFiles["localPath"]
|
objsLocal = objFiles["localPath"]
|
||||||
changeObjFile(objFiles["localPath"], f"{orderId}_{pid}.mtl")
|
changeObjFile(objFiles["localPath"], f"{orderId}_{pid}.mtl")
|
||||||
|
log(f"修改obj关联耗时: {time.time() - beginChangeTime}秒 - {objFiles['localPath']}")
|
||||||
if objFiles["localPath"].endswith(".mtl"):
|
if objFiles["localPath"].endswith(".mtl"):
|
||||||
changeMtlFile(objFiles["localPath"], f"{orderId}_{pid}Tex1.jpg")
|
changeMtlFile(objFiles["localPath"], f"{orderId}_{pid}Tex1.jpg")
|
||||||
|
|
||||||
@@ -313,18 +320,56 @@ def _process_single_item(v, arrDownloadPath, dirNewName, dirPath, isSmallMachine
|
|||||||
# 获取 small_machine_transform.py 的绝对路径
|
# 获取 small_machine_transform.py 的绝对路径
|
||||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
transform_script_path = os.path.join(script_dir, 'small_machine_transform.py')
|
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)
|
||||||
# 使用 shlex.quote 来安全地转义路径和参数
|
|
||||||
transform_script_path_quoted = shlex.quote(transform_script_path)
|
# 构建命令参数列表(使用列表形式,避免 shell 转义问题)
|
||||||
objsLocal_quoted = shlex.quote(objsLocal)
|
cmd = [
|
||||||
homo_matrix_quoted = shlex.quote(homo_matrix_json)
|
blender_bin_path,
|
||||||
error = os.system(f"{blender_bin_path} -b -P {transform_script_path_quoted} -- --objPathName={objsLocal_quoted} --trans={homo_matrix_quoted}")
|
'--background',
|
||||||
if error != 0:
|
'--python',
|
||||||
error_msg = f"调用blender 执行 python 文件失败, error={error}, fileName={fileName}"
|
transform_script_path,
|
||||||
|
'--',
|
||||||
|
f'--objPathName={objsLocal}',
|
||||||
|
f'--trans={homo_matrix_json}'
|
||||||
|
]
|
||||||
|
|
||||||
|
log(f"执行 Blender 命令: {' '.join(cmd[:4])} ... (参数已隐藏)")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 使用 subprocess 执行命令,捕获输出和错误
|
||||||
|
# 在 Windows 上,Blender 输出可能是 UTF-8,需要指定编码并处理错误
|
||||||
|
result = subprocess.run(
|
||||||
|
cmd,
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
encoding='utf-8', # 指定 UTF-8 编码
|
||||||
|
errors='replace', # 遇到无法解码的字符时替换为占位符,而不是抛出异常
|
||||||
|
timeout=300, # 5分钟超时
|
||||||
|
check=False # 不自动抛出异常,手动检查返回码
|
||||||
|
)
|
||||||
|
|
||||||
|
if result.returncode != 0:
|
||||||
|
error_output = result.stderr if result.stderr else result.stdout
|
||||||
|
error_msg = f"调用blender 执行 python 文件失败, error={result.returncode}, fileName={fileName}"
|
||||||
|
if error_output:
|
||||||
|
error_msg += f", 错误信息: {error_output[:500]}" # 限制错误信息长度
|
||||||
|
log(error_msg)
|
||||||
|
return False, error_msg
|
||||||
|
|
||||||
|
log(f"调用blender 执行 python 文件成功, fileName={fileName}")
|
||||||
|
if result.stdout:
|
||||||
|
log(f"Blender 输出: {result.stdout[:200]}") # 记录部分输出用于调试
|
||||||
|
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
error_msg = f"调用blender 执行超时(超过5分钟), fileName={fileName}"
|
||||||
|
log(error_msg)
|
||||||
|
return False, error_msg
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = f"调用blender 执行时发生异常: {str(e)}, fileName={fileName}"
|
||||||
log(error_msg)
|
log(error_msg)
|
||||||
return False, error_msg
|
return False, error_msg
|
||||||
log(f"调用blender 执行 python 文件成功, error={error}, fileName={fileName}")
|
|
||||||
|
|
||||||
timeEnd = time.time()
|
timeEnd = time.time()
|
||||||
log(f"转换数据时间: 耗时{timeEnd - timeBegin}秒 - {objsLocal}")
|
log(f"转换数据时间: 耗时{timeEnd - timeBegin}秒 - {objsLocal}")
|
||||||
@@ -337,7 +382,7 @@ def _process_single_item(v, arrDownloadPath, dirNewName, dirPath, isSmallMachine
|
|||||||
|
|
||||||
|
|
||||||
# json文件进行下载对应的数据 和转换数据,传递目录路径
|
# json文件进行下载对应的数据 和转换数据,传递目录路径
|
||||||
def downloadDataByOssAndTransformSave(dirNewName,isSmallMachine=False, max_workers=10):
|
def downloadDataByOssAndTransformSave(dirNewName, isSmallMachine=False, max_workers=1):
|
||||||
listData = getJsonData(dirNewName)
|
listData = getJsonData(dirNewName)
|
||||||
if not listData:
|
if not listData:
|
||||||
log(f"获取数据失败, dirNewName={dirNewName}")
|
log(f"获取数据失败, dirNewName={dirNewName}")
|
||||||
@@ -405,14 +450,35 @@ def downloadDataByOssAndTransformSave(dirNewName,isSmallMachine=False, max_worke
|
|||||||
|
|
||||||
|
|
||||||
def findBpyModule():
|
def findBpyModule():
|
||||||
# 返回 Blender 可执行文件路径(macOS)
|
# 返回 Blender 可执行文件路径
|
||||||
blender_bin_path = '/Applications/Blender.app/Contents/MacOS/Blender'
|
blender_bin_path = '/Applications/Blender.app/Contents/MacOS/Blender'
|
||||||
# 判断当前是 windows 还是 macOS
|
# 判断当前是 windows 还是 macOS
|
||||||
if platform.system() == 'Windows':
|
if platform.system() == 'Windows':
|
||||||
|
# Windows 上常见的 Blender 安装路径
|
||||||
|
possible_paths = [
|
||||||
|
'C:\\Program Files\\Blender Foundation\\Blender 5.0\\blender.exe',
|
||||||
|
'C:\\Program Files\\Blender Foundation\\Blender 4.4\\blender.exe',
|
||||||
|
'C:\\Program Files\\Blender Foundation\\Blender 4.3\\blender.exe',
|
||||||
|
'C:\\Program Files\\Blender Foundation\\Blender 4.2\\blender.exe',
|
||||||
|
'C:\\Program Files\\Blender Foundation\\Blender 4.1\\blender.exe',
|
||||||
|
'C:\\Program Files\\Blender Foundation\\Blender 4.0\\blender.exe',
|
||||||
|
]
|
||||||
|
# 查找存在的路径
|
||||||
|
for path in possible_paths:
|
||||||
|
if os.path.exists(path):
|
||||||
|
blender_bin_path = path
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
# 如果都没找到,使用默认路径
|
||||||
blender_bin_path = 'C:\\Program Files\\Blender Foundation\\Blender 5.0\\blender.exe'
|
blender_bin_path = 'C:\\Program Files\\Blender Foundation\\Blender 5.0\\blender.exe'
|
||||||
|
log(f"警告: 未找到 Blender 可执行文件,使用默认路径: {blender_bin_path}")
|
||||||
else:
|
else:
|
||||||
blender_bin_path = '/Applications/Blender.app/Contents/MacOS/Blender'
|
blender_bin_path = '/Applications/Blender.app/Contents/MacOS/Blender'
|
||||||
|
|
||||||
|
# 检查路径是否存在
|
||||||
|
if not os.path.exists(blender_bin_path):
|
||||||
|
error_msg = f"Blender 可执行文件不存在: {blender_bin_path}"
|
||||||
|
log(error_msg)
|
||||||
|
raise FileNotFoundError(error_msg)
|
||||||
|
|
||||||
return blender_bin_path
|
return blender_bin_path
|
||||||
Reference in new issue
Block a user