从线程返回值

Pau*_*eph 56 python multithreading exit-code python-multithreading

我如何让一个线程将一个元组或我选择的任何值返回给Python中的父元素?

Ale*_*lli 59

我建议你在启动线程之前实例化一个Queue.Queue,并将其作为线程的一个args传递:在线程完成之前,它.put是作为参数接收的队列的结果.父母可以.get或随意.get_nowait.

队列通常是在Python中安排线程同步和通信的最佳方式:它们本质上是线程安全的,消息传递工具 - 一般来说组织多任务处理的最佳方式! - )

  • 它很丑陋,专门针对现有的功能; 并且Queue对于单个结果问题有很多不必要的开销.更清晰有效地子类`threading.Thread`和新的run()方法只是将结果存储为属性,如`self.ret = ...`(更舒适的是Thread的子类,它处理返回值/异常确实应该扩展`threading.Thread`以提供开箱即用的功能 - 因为它与旧行为兼容"返回无".) (3认同)
  • `在线程完成之前,它.将结果输出到它作为参数接收的队列中你的意思是这将由python自动完成?如果不是(意思是设计提示)那么你能否在答案中说清楚. (2认同)

Pet*_*sen 12

如果你正在调用join()来等待线程完成,你可以简单地将结果附加到Thread实例本身,然后在join()返回后从主线程中检索它.

另一方面,您没有告诉我们您打算如何发现线程已完成以及结果是否可用.如果你已经有办法做到这一点,它可能会指出你(和我们,如果你告诉我们)最好的方法来获得结果.

  • 如果`join()`只返回被调用的方法返回的内容,那就太好了......看起来很傻,而不是返回`None`. (6认同)

Fat*_*ana 12

您应该将Queue实例作为参数传递,然后将.put()返回对象放入队列中.您可以通过queue.get()收集返回值,无论您放置什么对象.

样品:

queue = Queue.Queue()
thread_ = threading.Thread(
                target=target_method,
                name="Thread1",
                args=[params, queue],
                )
thread_.start()
thread_.join()
queue.get()

def target_method(self, params, queue):
 """
 Some operations right here
 """
 your_return = "Whatever your object is"
 queue.put(your_return)
Run Code Online (Sandbox Code Playgroud)

用于多个线程:

#Start all threads in thread pool
    for thread in pool:
        thread.start()
        response = queue.get()
        thread_results.append(response)

#Kill all threads
    for thread in pool:
        thread.join()
Run Code Online (Sandbox Code Playgroud)

我使用这个实现,它对我很有用.我希望你这样做.


Pet*_*řek 9

使用lambda来包装目标线程函数,并使用队列将其返回值传递回父线程.(没有额外的队列参数,您的原始目标函数保持不变.)

示例代码:

import threading
import queue
def dosomething(param):
    return param * 2
que = queue.Queue()
thr = threading.Thread(target = lambda q, arg : q.put(dosomething(arg)), args = (que, 2))
thr.start()
thr.join()
while not que.empty():
    print(que.get())
Run Code Online (Sandbox Code Playgroud)

输出:

4
Run Code Online (Sandbox Code Playgroud)


jco*_*ctx 7

我很惊讶没有人提到你可以把它变成一个可变的:

>>> thread_return={'success': False}
>>> from threading import Thread
>>> def task(thread_return):
...  thread_return['success'] = True
... 
>>> Thread(target=task, args=(thread_return,)).start()
>>> thread_return
{'success': True}
Run Code Online (Sandbox Code Playgroud)

也许这有一些我不知道的重大问题.


Vij*_*hew 5

另一种方法是将回调函数传递给线程.这提供了一种简单,安全且灵活的方式,可以随时从新线程向父项返回值.

# A sample implementation

import threading
import time

class MyThread(threading.Thread):
    def __init__(self, cb):
        threading.Thread.__init__(self)
        self.callback = cb

    def run(self):
        for i in range(10):
            self.callback(i)
            time.sleep(1)


# test

import sys

def count(x):
    print x
    sys.stdout.flush()

t = MyThread(count)
t.start()
Run Code Online (Sandbox Code Playgroud)

  • 这个问题是回调仍然在子线程中运行,而不是在原始线程中运行. (8认同)
  • 好.一个示例是,如果回调写入父线程在线程运行时也写入的日志文件.由于回调在子线程中运行,因此存在两次写入同时发生并发生冲突的风险 - 您可能会出现乱码或交错输出,或者如果日志框架执行了一些内部簿记,则会发生崩溃.使用线程安全队列并让一个线程完成所有写操作都可以避免这种情况.这些问题可能是令人讨厌的,因为它们不是确定性的 - 它们可能只会出现在生产中,并且很难再现. (4认同)