Python线程未等待问题:或与面向对象设计及传参错误有关
处理大文件加载时的线程异常问题
在基于DearPyGUI开发GUI界面时,需加载3GB级大文件,因此采用线程优化长IO操作。在类实例方法中启动线程调用同类方法更新对象属性时,出现两个异常:
- 线程抛出
TypeError(方法参数数量不匹配) - 主线程执行
thread.join()后,调用属性的getVersion()方法触发AttributeError(属性为None)
线程未完成IO操作就终止,主线程未等待其执行完毕。
原代码
class IOClass: __init__(self): self.fileObj = None def loadFile(self, fileName): thread = threading.Thread(target=self.threadMethod, args=fileName) thread.start() #Load GUI wait-screen thread.join() #anything else..EXCEPTION THROWN HERE print(" ".join(["Version:", self.fileObj.getVersion()])) def threadMethod(self, fileName): print(" ".join(["Loading filename", fileName])) #expensive-basic Python IO operation here self.fileObj = ...python IO operation here class GUIClass: __init__(self): pass def startMethod(self): #this is called by __main__ ioClass = IOClass() ioClass.loadFile("filename.txt")
报错信息
Exception in thread Thread-1 (loadFile): Traceback (most recent call last): File "/home/anthony/anaconda3/envs/CPRD-software/lib/python3.10/threading.py", line 1009, in _bootstrap_inner self.run() File "/home/anthony/anaconda3/envs/CPRD-software/lib/python3.10/threading.py", line 946, in run self._target(*self._args, **self._kwargs) TypeError: AnalysisController.loadFile() takes 2 positional arguments but 25 were given Traceback (most recent call last): File "/home/anthony/CPRD-software/GUI/Controllers/AnalysisController.py", line 117, in loadStudySpace print(" ".join(["Version:", self.fileObj.getVersion()])) AttributeError: 'NoneType' object has no attribute 'getVersion'
问题根源与解决方案
问题分析
创建Thread对象时,args参数需传入元组,但原代码直接传入字符串fileName。字符串会被Python视为可迭代对象,拆分为单个字符作为多个参数传递给threadMethod,导致方法参数数量不匹配,触发TypeError。线程因异常终止后,self.fileObj未被赋值,主线程访问时自然抛出AttributeError。
修正代码
只需将args参数改为元组格式(注意末尾的逗号,确保是元组而非单个元素),同时补充原代码遗漏的def关键字:
class IOClass: def __init__(self): self.fileObj = None def loadFile(self, fileName): # 修正args为元组格式 thread = threading.Thread(target=self.threadMethod, args=(fileName,)) thread.start() #Load GUI wait-screen thread.join() print(" ".join(["Version:", self.fileObj.getVersion()])) def threadMethod(self, fileName): print(" ".join(["Loading filename", fileName])) #expensive-basic Python IO operation here self.fileObj = ...python IO operation here class GUIClass: def __init__(self): pass def startMethod(self): #this is called by __main__ ioClass = IOClass() ioClass.loadFile("filename.txt")
内容的提问来源于stack exchange,提问作者Anthony Nash
相关产品推荐
相关产品推荐

