Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python中线程之间的通信(不使用全局变量)_Python_Multithreading - Fatal编程技术网

Python中线程之间的通信(不使用全局变量)

Python中线程之间的通信(不使用全局变量),python,multithreading,Python,Multithreading,假设我们有一个主线程,它为测试模块启动两个线程——“test_a”和“test_b”。 无论测试模块线程是否已完成测试,或者是否遇到任何错误、警告或是否要更新某些其他信息,这两个测试模块线程都会保持其状态 主线程如何访问这些信息并相应地采取行动。 例如,如果“test_a”引发错误标志;“main”将如何知道并停止其余的测试,直到出现错误 实现这一点的一种方法是使用全局变量,但这会变得非常糟糕。。很快。显而易见的解决方案是共享某种可变变量,通过在构造函数/开始时将其传递给线程对象/函数 实现这一

假设我们有一个主线程,它为测试模块启动两个线程——“test_a”和“test_b”。 无论测试模块线程是否已完成测试,或者是否遇到任何错误、警告或是否要更新某些其他信息,这两个测试模块线程都会保持其状态

主线程如何访问这些信息并相应地采取行动。 例如,如果“test_a”引发错误标志;“main”将如何知道并停止其余的测试,直到出现错误


实现这一点的一种方法是使用全局变量,但这会变得非常糟糕。。很快。

显而易见的解决方案是共享某种可变变量,通过在构造函数/开始时将其传递给线程对象/函数

实现这一点的干净方法是使用适当的实例属性构建一个类。如果您使用的是
threading.Thread
,而不仅仅是线程函数,那么通常可以使用子类本身作为粘贴这些属性的位置。但我会用
列表显示它,因为它比较短:

def test_a_func(thread_state):
    # ...
    thread_state[0] = my_error_state
    # ...

def main_thread():
    test_states = [None]
    test_a = threading.Thread(target=test_a_func, args=(test_states,))
    test_a.start()
您还可以(通常希望)将
条件
打包到可变状态对象中,这样您就可以在
主线程
测试a
之间正确同步

(另一个选项是使用
queue.queue
、操作系统管道等来传递信息,但仍然需要将该队列或管道发送到子线程,方法与上面完全相同。)


然而,你是否真的需要这样做是值得考虑的。如果将
test_a
test_b
视为“作业”,而不是“线程函数”,则可以在池上执行这些作业,并让池处理返回的结果或错误

例如:

try:
    with concurrent.futures.ThreadPoolExecutor(workers=2) as executor:
        tests = [executor.submit(job) for job in (test_a, test_b)]
        for test in concurrent.futures.as_completed(tests):
            result = test.result()
except Exception as e:
    # do stuff
现在,如果
test\u a
函数引发异常,主线程将获得该异常,因为这意味着退出带有
块的
,所有其他作业将被取消并丢弃,工作线程将关闭


如果您使用的是2.5-3.1,那么您没有内置的
concurrent.futures
,但是您可以安装,也可以重写
multiprocessing.dummy.Pool
。(这样做稍微复杂一些,因为您必须创建一系列作业并调用
map\u async
以获取
AsyncResult
对象上的迭代器……但实际上这仍然非常简单。)

+1
concurrent.futures
。我从来不知道-但可能是因为它们是3+?@naxa:它只存在于3.2+中的stdlib中,但是有,或者你可以在
多处理.ThreadPool
(我相信在2.x中没有记录,但一直存在)的基础上非常容易地构建它的子集(你需要的所有部分)。