Pymeshlab大脚本偶报文件不存在但实际存在的原因排查
问题描述
我编写了两个PyMeshLab脚本处理OBJ文件,遇到了偶发的文件加载异常:
脚本1(短脚本)
import os import argparse import pymeshlab from collections import Counter def load_mesh(file_path): ms = pymeshlab.MeshSet() ms.load_new_mesh(file_path) measures = ms.get_topological_measures() print(measures) def main(): parser = argparse.ArgumentParser(description="Count the number of 'ok' meshes in a directory.") parser.add_argument("-i", "--input", required=True, help="Path to the directory containing OBJ files.") args = parser.parse_args() results = load_mesh(args.input) if __name__ == "__main__": main()
脚本2(长脚本)
import os import argparse import pymeshlab from collections import Counter def is_mesh_ok(file_path): try: ms = pymeshlab.MeshSet() ms.load_new_mesh(file_path) measures = ms.get_topological_measures() except Exception as e: print(f"Failed to load mesh '{file_path}': {e}") return "Load Failed" genus = measures['genus'] connected_components = measures['connected_components_number'] is_two_manifold = measures['is_mesh_two_manifold'] hole_count = measures['number_holes'] is_ok = (genus == 0) and (connected_components == 1) and (is_two_manifold is True) and (hole_count == 0) if is_ok: return "OK" else: failed_criteria = [] if genus != 0: failed_criteria.append("Genus") if connected_components != 1: failed_criteria.append("Connected Components") if not is_two_manifold: failed_criteria.append("Is Two Manifold") if hole_count != 0: failed_criteria.append("Number of Holes") return ", ".join(failed_criteria) def count_ok_meshes(directory_path): results = [] for filename in os.listdir(directory_path): if filename.endswith('.obj'): file_path = os.path.join(directory_path, filename) result = is_mesh_ok(file_path) results.append(result) return results def main(): parser = argparse.ArgumentParser(description="Count the number of 'ok' meshes in a directory.") parser.add_argument("-d", "--directory", required=True, help="Path to the directory containing OBJ files.") args = parser.parse_args() results = count_ok_meshes(args.directory) counter = Counter(results) print("Histogram of Failed Criteria:") for key, value in counter.items(): print(f"{key}: {value}") if __name__ == "__main__": main()
异常现象
- 短脚本可正常加载目录下所有OBJ文件,返回拓扑测量结果。
- 长脚本会偶发报错部分文件不存在,错误示例:
Failed to load mesh 'clean_results/mesh703.obj': File does not exists: clean_results/mesh703.obj
- 报错文件不固定,每次运行脚本都会变化,且报错文件在短脚本中能正常加载。
原因分析
核心问题是PyMeshLab批量创建MeshSet实例时的资源冲突:
- 长脚本在循环中反复创建
MeshSet对象,PyMeshLab底层的C++资源未及时释放,导致路径解析模块出现偶发混乱,将正确路径误判为不存在。 - 短脚本仅创建一次
MeshSet,无频繁实例化带来的资源竞争,路径解析始终正常。
另外,虽然用os.path.join拼接了路径,但高频率调用PyMeshLab加载函数时,可能因缓存或资源未释放,出现相对路径解析错误。
解决方案
方案1:复用单个MeshSet实例
避免循环中反复创建MeshSet,初始化一次后用load_new_mesh替换旧网格:
def is_mesh_ok(ms, file_path): try: ms.load_new_mesh(file_path) # 替换现有网格 measures = ms.get_topological_measures() except Exception as e: print(f"Failed to load mesh '{file_path}': {e}") return "Load Failed" # 原判断逻辑保持不变... def count_ok_meshes(directory_path): results = [] ms = pymeshlab.MeshSet() # 仅初始化一次 for filename in os.listdir(directory_path): if filename.endswith('.obj'): file_path = os.path.join(directory_path, filename) result = is_mesh_ok(ms, file_path) results.append(result) return results
方案2:使用绝对路径
确保传入PyMeshLab的是绝对路径,避免路径解析错误:
def count_ok_meshes(directory_path): results = [] abs_dir = os.path.abspath(directory_path) # 转为绝对路径 for filename in os.listdir(abs_dir): if filename.endswith('.obj'): file_path = os.path.join(abs_dir, filename) result = is_mesh_ok(file_path) results.append(result) return results
额外优化:添加文件存在性检查
在调用PyMeshLab加载前,先确认文件存在,排除其他可能性:
def is_mesh_ok(file_path): if not os.path.isfile(file_path): print(f"File does not exist: {file_path}") return "Load Failed" try: ms = pymeshlab.MeshSet() ms.load_new_mesh(file_path) measures = ms.get_topological_measures() except Exception as e: print(f"Failed to load mesh '{file_path}': {e}") return "Load Failed" # 原判断逻辑保持不变...
内容的提问来源于stack exchange,提问作者Makogan
相关产品推荐
相关产品推荐

