You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用元类实现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}")

关键调整说明

  1. 新增线程目标函数:定义了create_file_in_thread函数,让线程执行这个函数,在函数内部完成File类的实例化,这才符合你“用线程实例化类”的需求。
  2. 修复Thread参数:给Thread的target传递可调用的函数,而不是对象实例,彻底解决了TypeError问题。
  3. 保留线程安全单例:你用元类+Lock实现的线程安全单例是正确的,修正后的代码依然能保证多线程下只会创建一个File实例,所有实例的哈希值完全一致。

预期运行效果

运行后你会看到所有线程和主线程中创建的File对象地址、哈希值完全相同,证明单例模式生效,同时不会再出现任何报错,还能正常打印文件名属性。

内容的提问来源于stack exchange,提问作者Fabricio Nahuel Rori

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 10:05:25