使用元类实现Python单例时遇线程报错:'File'对象不可调用
嘿,我来帮你梳理清楚这个问题并解决它!
问题根源
你看到的TypeError: 'File' object is not callable报错,核心原因是你给threading.Thread的target参数传错了东西:Thread的target需要接收一个可调用对象(比如函数、类的方法,或者实现了__call__魔法方法的对象),但你直接传了File类的实例(file_1和file_2),而你的File类并没有定义__call__方法,所以这些实例没法被线程调用,自然就报错了。
另外,你的代码逻辑和你描述的“创建两个线程实例化File类”也不匹配——你是在主线程提前实例化了对象,然后把实例传给线程,这根本不是让线程去实例化类的操作哦。
修正后的完整代码
我调整了代码逻辑,让每个线程内部去实例化File类,同时保留了线程安全的单例实现,还能验证哈希值是否一致:
# -*- coding: utf-8 -*- import pathlib import threading from threading import Lock class Singleton(type): _instances = {} _lock: Lock = Lock() def __call__(cls, *args, **kwargs): with cls._lock: if cls not in cls._instances: cls._instances[cls] = super().__call__(*args, **kwargs) return cls._instances[cls] class File(metaclass=Singleton): def __init__(self): self._file = str(pathlib.Path(__file__).name) @property def get_file(self): return self._file def create_file_in_thread(thread_label): """线程执行的函数:实例化File并打印验证信息""" file_obj = File() print(f"{thread_label} 创建的File对象: {file_obj} | 哈希值: {hash(file_obj)}") print(f"{thread_label} 获取的文件名: {file_obj.get_file}\n") if __name__ == '__main__': # 创建两个线程,每个线程执行实例化操作 thread1 = threading.Thread(target=create_file_in_thread, args=("线程1",)) thread2 = threading.Thread(target=create_file_in_thread, args=("线程2",)) thread1.start() thread2.start() thread1.join() thread2.join() # 主线程再验证一次单例效果 print("=== 主线程验证 ===") main_file1 = File() main_file2 = File() print(f"主线程实例1: {main_file1} | 哈希值: {hash(main_file1)}") print(f"主线程实例2: {main_file2} | 哈希值: {hash(main_file2)}") print(f"文件名: {main_file1.get_file}")
关键调整说明
- 新增线程目标函数:定义了
create_file_in_thread函数,让线程执行这个函数,在函数内部完成File类的实例化,这才符合你“用线程实例化类”的需求。 - 修复Thread参数:给
Thread的target传递可调用的函数,而不是对象实例,彻底解决了TypeError问题。 - 保留线程安全单例:你用元类+Lock实现的线程安全单例是正确的,修正后的代码依然能保证多线程下只会创建一个
File实例,所有实例的哈希值完全一致。
预期运行效果
运行后你会看到所有线程和主线程中创建的File对象地址、哈希值完全相同,证明单例模式生效,同时不会再出现任何报错,还能正常打印文件名属性。
内容的提问来源于stack exchange,提问作者Fabricio Nahuel Rori
相关产品推荐
相关产品推荐

