通过线程类传递变量

时间:2017-11-21 20:02:55

标签: python multithreading

在下面的测试代码中,

class1.stop_callback()设置class1.stop = True

因此class2.stop = True

因此class3.stop应该是True,但它不是。

class1.stop_callback()应该停止程序,但它不会这样做。 我做错了什么?

您可以在repl.it 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()

2 个答案:

答案 0 :(得分:1)

在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

答案 1 :(得分:1)

由于Class3不是类似Thread的类(尽管未在主线程中运行),因此在class3.stop返回之前,您无法更改class3.foo()的值。由于class3.foo()class3.stop的值发生变化之前不会返回,因此无法停止该过程并且它会永远运行。

我建议在Class3上设置Thread,以便在运行时调用方法。如果这是一个过多的开销,或者每个class2实例将运行多次,您可以随时定义foo然后在Class2.run方法中运行它。

编辑:我要提到弗洛里安的观点,但是因为 - 在他提出的解决方案中 - 可变对象在任务期间进行,我不确定你是否已经考虑过这一部分

以下是修订后的代码;注

  • 使用threading.Lock来防止在同一行发生的那些奇怪的打印陈述
  • while not self.stop使用if而不是break
  • {/ 1}}
  • 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()