通过线程类传递变量

2024-04-26 15:12:00 发布

您现在位置:Python中文网/ 问答频道 /正文

在下面的测试代码中

class1.stop\u callback()设置class1.stop=True

因此class2.stop=True

因此class3.stop应该是真的,但事实并非如此

stop\u callback()应该停止程序,但它不会这样做。 我做错什么了?你知道吗

你可以在上面测试代码复制https://repl.it/@bahtsiz_bedevi/classtest

import threading
import time


class Class1(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.stop = False

    def stop_callback(self):
        self.stop = True

    def run(self):
        class2 = Class2()
        class2.stop = self.stop
        class2.start()
        while True:
            time.sleep(1)
            print("{} stop status: {}".format(self.__class__, "True" if self.stop else "False"))
            if self.stop:
                break


class Class2(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.stop = False

    def run(self):
        class3 = Class3()
        class3.stop = self.stop
        while True:
            time.sleep(1)
            print("{} stop status: {}".format(self.__class__, "True" if self.stop else "False"))
            if self.stop:
                break
            class3.foo()


class Class3:
    def __init__(self):
        self.stop = False

    def foo(self):
        while True:
            time.sleep(1)
            print("{} stop status: {}".format(self.__class__, "True" if self.stop else "False"))
            if self.stop:
                break


class1 = Class1()
class1.start()
for i in range(10):
    time.sleep(1)
class1.stop_callback()

Tags: selffalsetrueiftimeinitdefcallback
2条回答

在Python中,变量是对象的名称。通过将False分配给class1.stopclass1.stop分配给class2.stop,您将False分配给class2.stop,仅此而已。你知道吗

您似乎想要的是对class1.stop的引用,然而这不是Python中赋值的工作方式。解决这个问题的一种方法是使用列表。如果保持列表不变,只更改第一个索引处的值,则可以实现所需的:

stop1 = [False]
stop2 = stop1
assert stop2[0] == False
stop1[0] = True
assert stop2[0] == True

因为Class3不是类似于Thread的类(尽管没有在主线程中运行),所以在class3.foo()返回之前不能更改class3.stop的值。由于class3.foo()class3.stop的值更改之前不会返回,因此无法停止进程,进程将永远运行。你知道吗

我建议将Class3建立在Thread之上,这样您就可以在它运行时调用它的方法。如果这是太多的开销,或者每个class2实例都要多次运行它,那么您总是可以定义foo,然后在Class2.run方法中运行它。你知道吗


编辑:我本想提到弗洛里安的观点,但由于正如他提出的解决方案一样,可变对象在分配任务时会发生变化,我不确定你是否已经仔细考虑了这一部分。你知道吗

以下是修订后的代码;注

  • 使用threading.Lock来防止在同一行中出现那些奇怪的打印语句
  • 使用while not self.stop而不是带有breakif语句
  • 线程在Class3中的使用

import threading
import time

printLock = threading.Lock()
p = print

def print(*a, **b):
    with printLock:
        p(*a, **b)


class Class1(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.stop = False

    def stopMe(self):
        self.stop = True

    def run(self):
        class2 = Class2()
        class2.start()
        while not self.stop:
            time.sleep(1)
            print("{} stop status:{:6}".format(self.__class__, str(self.stop)))
        class2.stopMe()


class Class2(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.stop = False

    def stopMe(self):
        self.stop = True

    def run(self):
        class3 = Class3()
        class3.start()
        while not self.stop:
            time.sleep(1)
            print("{} stop status:{:6}".format(self.__class__, str(self.stop)))
        class3.stopMe()


class Class3(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.stop = False

    def stopMe(self):
        self.stop = True

    def run(self):
        while not self.stop:
            time.sleep(1)
            print("{} stop status:{:6}".format(self.__class__, str(self.stop)))


class1 = Class1()
class1.start()
time.sleep(10)
class1.stopMe()

相关问题 更多 >