向Python线程发送参数会阻止其他线程

时间:2013-06-14 14:50:14

标签: python multithreading oop python-3.x

考虑这个测试应用程序将参数传递给Python线程:

#!/usr/bin/python3

from pprint import pprint
import signal
import sys
import threading


class CallThreads(threading.Thread):

    def __init__(self, target, *args):
        self._target = target
        threading.Thread.__init__(self)
        target(*args)

def main(argv):
    phrases = ['hello', 'goodbye']
    num = 0

    for phrase in phrases:
        num += 1
        thread_handler = CallThreads(someFunction, phrase, num)
        thread_handler.daemon = True
        thread_handler.start()

    return True


def someFunction(a, b):
    print("Hi: "+str(a)+" and "+str(b))
    return True


def signal_handler(signal, frame):
    print(["Got SIGINT!"])
    sys.exit(0)


if __name__ == '__main__':
    signal.signal(signal.SIGINT, signal_handler)
    main(sys.argv)

在它的当前状态下,似乎for phrase in phrases循环在启动另一个线程之前等待线程完成。也就是说,如果someFunction()需要很长时间才能完成,那么下一个线程将不会启动,直到前一个线程返回。为什么会这样,以及如何在仍然向线程发送参数的同时解决它?

修改 我尝试在args中将self._args数组保存在构造函数中,然后在self._target(*self._args)中调用self._target(self._args)def run (self):。这实际上适用于Python 2,但不适用于Python 3.我该怎么办?

修改 似乎问题是在Python 3中,run方法无法访问私有变量。也就是说,对于以下改进的代码:

def __init__(self, target, *args):
    self._args = args
    threading.Thread.__init__(self)

def run(self):
    someFunction(*self._args)

请注意以下输出:

Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python3.3/threading.py", line 639, in _bootstrap_inner
    self.run()
  File "./test.py", line 19, in run
    someFunction(*self._args)
TypeError: someFunction() missing 2 required positional arguments: 'a' and 'b'

pprint(self._args)方法添加run()确实表明返回的元组为空。但是,将变量更改为非私有作品!以下代码运行正常:

def __init__(self, target, *args):
    self.target = target
    self.args = args
    threading.Thread.__init__(self)

def run(self):
    self.target(*self.args)

因此,我可以在Python 3中使用带有公共变量的应用程序。但是,有没有办法在CallThreads类中使用私有变量,就像在Python 2中一样?

谢谢!

1 个答案:

答案 0 :(得分:4)

问题是您在target(args)的构造函数上调用CallThreads

因此,以下调用会阻止CallThreads.__init__()完成:

thread_handler = CallThreads(someFunction, phrase, num)

<强>更新 一种可能性如下:

class CallThreads(threading.Thread):

    def __init__(self, *args):
        self._args   = args
        threading.Thread.__init__(self)

    def run(self):
        someFunction(*self._args)