Autodesk 的 Fbx Python 和线程
Posted
技术标签:
【中文标题】Autodesk 的 Fbx Python 和线程【英文标题】:Autodesk's Fbx Python and threading 【发布时间】:2017-04-01 08:55:56 【问题描述】:我正在尝试使用来自 Autodesk 的 fbx python 模块,但似乎我无法执行任何操作。这似乎是由于 GIL 没有发布。有没有人发现同样的问题或者我做错了什么?当我说它不起作用时,我的意思是代码没有释放线程并且我不能做任何其他事情,而 fbx 代码正在运行。
没有太多代码可以发布,只是想知道是否有人尝试过。
更新:
这里是示例代码,请注意每个 fbx 文件大约是 2GB
import os
import fbx
import threading
file_dir = r'../fbxfiles'
def parse_fbx(filepath):
print '-' * (len(filepath) + 9)
print 'parsing:', filepath
manager = fbx.FbxManager.Create()
importer = fbx.FbxImporter.Create(manager, '')
status = importer.Initialize(filepath)
if not status:
raise IOError()
scene = fbx.FbxScene.Create(manager, '')
importer.Import(scene)
# freeup memory
rootNode = scene.GetRootNode()
def traverse(node):
print node.GetName()
for i in range(0, node.GetChildCount()):
child = node.GetChild(i)
traverse(child)
# RUN
traverse(rootNode)
importer.Destroy()
manager.Destroy()
files = os.listdir(file_dir)
tt = []
for file_ in files:
filepath = os.path.join(file_dir, file_)
t = threading.Thread(target=parse_fbx, args=(filepath,))
tt.append(t)
t.start()
【问题讨论】:
请同时分享代码,不释放线程。你会得到更好的回应。现在,我们甚至不知道您正在做什么或试图实现什么 由于 GIL,解释器实际上永远不会同时执行 Python 代码。 GIL 通常仅在发生 I/O 并且当前线程正在等待它完成时才释放。在此过程中,任何等待的线程都将有机会运行。因此,您的问题可能与您使用 fbx 模块这一事实无关。 @MoinuddinQuadri,示例代码已上传。 @martineau,谢谢,请看一下我发布的代码。 【参考方案1】:我看到的一个问题是您的traverse()
函数。它可能会递归地调用自己很多次。另一个是让所有线程同时打印东西。正确执行此操作需要协调对共享输出设备(即屏幕)的访问。一种简单的方法是创建和使用全局 threading.Lock
对象。
先创建一个全局的Lock
,防止线程同时打印:
file_dir = '../fbxfiles' # an "r" prefix needed only when path contains backslashes
print_lock = threading.Lock() # add this here
然后制作一个使用它的traverse()
的非递归版本:
def traverse(rootNode):
with print_lock:
print rootNode.GetName()
for i in range(node.GetChildCount()):
child = node.GetChild(i)
with print_lock:
print child.GetName()
我不清楚读取每个 fbxfile 的确切位置。如果这一切都是由于importer.Import(scene)
调用而发生的,那么这是任何其他线程唯一有机会运行的时间——除非在traverse()
函数中[也] 完成了某些I/O。
由于打印绝对是一种输出形式,因此完成后也可以进行线程切换。但是,如果函数所做的只是执行某种类型的计算,那么在执行过程中不会发生多线程。
一旦你让多重读取工作,如果多个 2GB fbxfiles 被多个不同的线程同时读取到内存中,你可能会遇到内存不足的问题。
【讨论】:
嗨,打印只是代表,最终结果应该保存在内存中的某个地方并通过 ui (qt) 报告。尝试了各种方法来完成这项工作,但似乎没有按预期工作(没有尝试锁定,因为没有 O(I/O)发生)。不过关于内存的好点。需要使用中型 fbx 来尝试(~400/600Mb),否则我的机器会爆炸。干杯。 如果没有 I/O,那么就没有机会发生多线程。无论如何,您可能需要使用traverse()
的非递归版本,因为对自身的每个嵌套调用都会占用内存,并且 Python 具有允许的最大递归深度。如果超过,将导致RuntimeError
。此外,如果最终结果保存在内存中,您将需要某种方法来控制从多个线程对它的并发访问(假设您的代码会执行一些 I 或 O 并释放 GIL 以便其他线程可以运行)。
刚想到这个办法:如果你的线程函数不做任何I/O,你可以强制它暂时释放GIL,从而给其他线程运行的机会,调用@987654331 @ 周期性地在traverse()
的循环内。以上是关于Autodesk 的 Fbx Python 和线程的主要内容,如果未能解决你的问题,请参考以下文章