当继承threading.Thread时出现"RuntimeError: thread.__init__() not called"错误

24

我需要运行与dirlist列表元素数量相同的Observer类线程。

当我在Python控制台中运行它时,它能够正常工作。

class Observer(Thread):
    def run(self):
        naptime = random.randint(1,10)
        print(self.name + ' starting, running for %ss.' % naptime)
        time.sleep(naptime)
        print(self.name + ' done')

observers = {}
for d in dirlist:
    observers[d] = Observer()
    observers[d].start()

但是当我尝试从一个主线程中执行此操作,该主线程应该生成观察者线程时,我会遇到错误。

class Master(Thread):
    def __init__(self, dirlist):
        self.dirlist = dirlist
    def run(self):
        observers = {}
        for d in dirlist:
            observers[d] = Observer()
            observers[d].start()
        while True:
            time.sleep(3600)

master_thread = Master(dirlist)
master_thread.start()

调用 Master.start 的结果是:

RuntimeError: thread.__init__() not called

这对我来说看起来很奇怪。
我无法理解两种情况之间的区别。
有人能找出解决我的问题的方法吗?

不知何故,以下代码没有引发错误,我不明白为什么。

class Master(Thread):
    def set(self, dirlist):
        self.dirlist = dirlist
    def run(self):
        observers = {}
        for d in dirlist:
            observers[d] = Observer()
            observers[d].start()
        while True:
            time.sleep(3600)

master_thread = Master()
master_thread.set(dirlist)
master_thread.start()

7
那就按照错误提示调用Thread.init()函数怎么样? - JBernardo
应为 for d in self.dirlist:。当前的代码中 for d in dirlist: 指向一个全局变量。为了成为正确的 示例,代码应该是完整的,并且提供一个最小的 Observer 实现,只包含可直接使用的代码(这意味着不要从解释器中复制 Python 提示符和缩进)。请编辑您的问题以修正示例。最后,请问您使用的是哪个版本的Python? - outis
3个回答

45
>>> master_thread.start()
RuntimeError: thread.__init__() not called

确保在Master.__init__中调用Thread.__init__()

class Master(Thread):
    def __init__(self, dirlist):
        super(Master, self).__init__()
        self.dirlist = dirlist

4
“Still doesn't work”不是一个很明确的错误信息。请更新您的问题,展示新的代码和新的错误信息! - SingleNegationElimination
1
值得注意的是,在Python3中调用父类方法的首选方式是使用 super() 而不带参数,以使代码更易于维护。因此该行代码变为: super().__init__() - sql_knievel

16

虽然我知道回答晚了,但是没关系,我是Python的新手,但是这个问题也发生在我身上过,所以我回到Python教程去看了一下,发现有些地方和我们尝试的不同,希望可以帮到你。

import threading

class Master(Thread):
    def set(self, dirlist):
        self.dirlist = dirlist
    def run(self):
        observers = {}
        for d in dirlist:
            ...

根据 Python 教程,class 的定义如下:

class Master(threading.Thread):

这行文字丢失了:

threading.Thread.__init__(self)

最终会变成这样:

import threading

class Master(threading.Thread):
    def __init__(self, dirlist):
        threading.Thread.__init__(self)
        self.dirlist = dirlist
    def run(self):
        observers = {}
        for d in dirlist:
            ...

这应该可以正常工作,至少对我来说有效。希望能帮到你。

你的第二次尝试使用set方法是可行的,因为你没有覆盖Thread类的__init__方法。因此父类的原始init方法被使用,它按照预期运行。


调用基类方法的适当方式是通过super() - Antony Hatchkins
你需要缩进这两个方法的定义,因为它们是 Master 类的成员。 - user1318499

6
错误很明显,你应该调用thread.__init__()
def __init__(self, dirlist):
    super(Master, self).__init__()
    self.dirlist = dirlist       

3
super调用不正确。您应该传递子类。 - user395760
@Nullpoet,使用调用Thread.__init__应该可以工作。确保没有其他问题。如果没有初始化,您不能使用dirlist参数。 - utdemir
根据文档,您可以使用更简单的形式super().__init__() - Pascal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接