【问题标题】:Sending arguments to Python threads blocks other threads向 Python 线程发送参数会阻塞其他线程
【发布时间】:2013-06-14 14:50:13
【问题描述】:

考虑将参数传递给 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 中,然后在def run (self): 中调用self._target(*self._args)self._target(self._args)。这实际上适用于 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'

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

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 中一样?

谢谢!

【问题讨论】:

  • 这个继承自ThreadCallThreads类的目的是什么?
  • @qwwqwwq:目的是方便向线程发送参数。在这种情况下,参数是phrase, num

标签: python multithreading oop python-3.x


【解决方案1】:

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

因此,在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)

【讨论】:

  • 如何解决这个问题?我尝试在构造函数中将args 数组保存在self._args 中,然后在def run (self): 中调用self._target(*self._args。这实际上适用于 Python 2,但不适用于 Python 3。我该怎么办?
  • 找出为什么它在 Python 3 中不起作用。通常这就是我所做的:将参数传递给 __init__,将它们存储为实例变量,并定义将使用的 run() 方法这些参数。
  • 为什么是实例变量?那不会让我用不同的参数调用多个线程。
  • 有趣的是,如果我将变量公开,那么它就可以工作!请参阅问题编辑。谢谢!
猜你喜欢
  • 2014-04-03
  • 2013-07-11
  • 1970-01-01
  • 1970-01-01
  • 2016-03-27
  • 2012-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多