华为云 Python SDK 查询工具。自动发现已安装 SDK 的服务包、Client类、API 方法、入参详情、类信息(__init__ 参数、属性、类型、描述),支持关键字搜索,快速定位目标 API 使用方法。
必须显式调用 super().__init__(),因为 threading.thread 的 start() 方法依赖 __init__() 中初始化的 _started 等内部状态,未调用会导致 runtimeerror。

为什么继承 threading.Thread 必须显式调用 super().__init__()
这个 RuntimeError: Thread.__init__() not called 不是语法错误,而是 threading.Thread 内部状态校验失败——它在 start() 时检查 self._started 是否已初始化,而该属性只在父类 __init__() 中设置。如果你重写了子类的 __init__() 却忘了调用 super().__init__(),对象就处于“半初始化”状态,start() 一触发就会报错。
常见错误写法和修正方式
典型翻车现场:只顾传参、忽略父类初始化。
import threading
<p>class MyWorker(threading.Thread):
def <strong>init</strong>(self, task_id):</p><h1>❌ 错误:完全没调用 super().<strong>init</strong>()</h1><pre class="brush:python;toolbar:false;"> self.task_id = task_id # 这行没问题,但缺了关键初始化
def run(self):
print(f"Working on {self.task_id}")t = MyWorker(42) t.start() # → RuntimeError: Thread.init() not called
✅ 正确做法:在子类 __init__() 开头或明确位置调用 super().__init__(),并注意参数传递顺序(尤其当你要传 name、daemon 等关键字参数时):
- 如果不需要额外参数,直接
super().__init__()就够了 - 如果要传
name或daemon,必须显式传给super().__init__(),不能只存为实例变量 - 自定义参数(如
task_id)应在super().__init__()之后赋值
class MyWorker(threading.Thread):
def __init__(self, task_id, name=None, daemon=False):
# ✅ 正确:把 threading.Thread 支持的参数传给父类
super().__init__(name=name, daemon=daemon)
self.task_id = task_id # 自定义字段放后面
<pre class="brush:python;toolbar:false;">def run(self):
print(f"Working on {self.task_id}")
容易被忽略的兼容性细节
Python 3.8+ 对 threading.Thread 的初始化做了更严格的检查,老代码在低版本能“侥幸运行”,升级后立刻暴露问题。另外两个易踩坑点:
-
super().__init__()必须在self被任何其他方法访问前调用,否则可能引发AttributeError(比如你在它之前就用了self.name) - 不要在
__init__()里调用self.start()—— 这不是构造函数该干的事,且此时线程对象还没完全初始化好 - 若使用
@property或__setattr__拦截了属性赋值,可能意外干扰threading.Thread的内部字段初始化,这种属于高阶陷阱,先确保基础调用正确再说
调试时怎么快速定位问题
报错堆栈里通常不会直接提示“你忘了 super().__init__()”,只会卡在 start() 的某一行。这时候可以:
- 在子类
__init__()开头加一句print("init start"),再在super().__init__()后加print("super done"),确认是否执行到了那里 - 检查
t._started(虽然它是私有属性):如果print(t._started)报AttributeError,基本坐实没调父类__init__() - 用 IDE 的“go to definition”跳转到
threading.Thread.__init__,看看它到底设置了哪些属性(比如_target、_args、_kwargs、_started),就知道漏掉初始化会断在哪
线程对象的初始化不是可选步骤,是强制契约。哪怕你只改了一个参数名,只要动了 __init__(),就必须对父类负责。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










