当前位置: 首页 > 面试题库 >

如何从流程或线程实例返回值?

窦华晖
2023-03-14
问题内容

因此,我想运行一个可以在网络上搜索信息或直接从我自己的mysql数据库搜索信息的功能。第一个过程很耗时,第二个过程相对较快。

考虑到这一点,我创建了一个开始此复合搜索(find_compound_view)的过程。如果该过程完成得相对较快,则表示该过程已存在于数据库中,因此我可以立即呈现结果。否则,我将渲染“
drax_retrieving_data.html”。

我想到的愚蠢解决方案是两次运行该函数,一次是检查进程是否花费很长时间,另一次是实际获取函数的返回值。这几乎是因为我不知道如何返回find_compound_view函数的值。我尝试了谷歌搜索,但似乎找不到如何从类Process中专门返回值的方法。

   p = Process(target=find_compound_view, args=(form,))
        p.start()
        is_running = p.is_alive()
        start_time=time.time()
        while is_running:
            time.sleep(0.05)
            is_running = p.is_alive()
            if time.time() - start_time > 10 :
                print('Timer exceeded, DRAX is retrieving info!',time.time() - start_time)
                return render(request,'drax_internal_dbs/drax_retrieving_data.html')
        compound = find_compound_view(form,use_email=False)

   if compound:
      data=*****
      return  render(request, 'drax_internal_dbs/result.html',data)

问题答案:

您将需要一个multiprocessing.Pipe或一个multiprocessing.Queue将结果发送回您的父流程。如果仅执行I /
0,则应使用aThread而不是a Process,因为它更轻巧,并且大多数时间都花在等待上。我向您展示了一般情况下进程和线程是如何完成的。

队列处理

多处理队列建立在管道的顶部,访问与锁/信号量同步。队列是线程安全和进程安全的,这意味着您可以将一个队列用于多个生产者/消费者进程,甚至这些进程中的多个线程。在队列中添加第一项也会在调用过程中启动一个供料器线程。在multiprocessing.Queue单个生产者/单个消费者的情况下使用管道的制造商的额外开销更可取,并且性能更高。

以下是发送和检索结果的方法multiprocessing.Queue

from multiprocessing import Process, Queue

SENTINEL = 'SENTINEL'

def sim_busy(out_queue, x):
    for _ in range(int(x)):
        assert 1 == 1
    result = x
    out_queue.put(result)
    # If all results are enqueued, send a sentinel-value to let the parent know
    # no more results will come.
    out_queue.put(SENTINEL)


if __name__ == '__main__':

    out_queue = Queue()

    p = Process(target=sim_busy, args=(out_queue, 150e6))  # 150e6 == 150000000.0
    p.start()

    for result in iter(out_queue.get, SENTINEL):  # sentinel breaks the loop
        print(result)

队列作为参数传递到函数中,结果.put()在队列中,而父对象get.()在队列中。.get()是一个阻塞调用,执行不恢复,直到事情
得到(指定超时参数是可能的)。请注意,sim_busy这里所做的工作是CPU密集型的,那就是您选择进程而不是线程。

工艺与管道

对于一对一连接,管道就足够了。设置几乎相同,只是方法的名称不同,并且调用Pipe()返回两个连接对象。在双工模式下,两个对象都是读写端,duplex=False(简单)第一个连接对象是管道的读端,第二个对象是写端。在这种基本情况下,我们只需要一个单纯形管道:

from multiprocessing import Process, Pipe

SENTINEL = 'SENTINEL'


def sim_busy(write_conn, x):
    for _ in range(int(x)):
        assert 1 == 1
    result = x
    write_conn.send(result)
    # If all results are send, send a sentinel-value to let the parent know
    # no more results will come.
    write_conn.send(SENTINEL)


if __name__ == '__main__':

    # duplex=False because we just need one-way communication in this case.
    read_conn, write_conn = Pipe(duplex=False)

    p = Process(target=sim_busy, args=(write_conn, 150e6))  # 150e6 == 150000000.0
    p.start()

    for result in iter(read_conn.recv, SENTINEL):  # sentinel breaks the loop
        print(result)

线程和队列

要与线程一起使用,您想要切换到queue.Queuequeue.Queue是在之上构建的collections.deque,添加了一些锁以使其具有线程安全性。与多重处理的队列和管道不同,放置在queue.Queue容器上的对象不会被腌制。由于线程共享相同的内存地址空间,因此无需进行用于内存复制的序列化,因此仅传输指针。

from threading import Thread
from queue import Queue
import time

SENTINEL = 'SENTINEL'


def sim_io(out_queue, query):
    time.sleep(1)
    result = query + '_result'
    out_queue.put(result)
    # If all results are enqueued, send a sentinel-value to let the parent know
    # no more results will come.
    out_queue.put(SENTINEL)


if __name__ == '__main__':

    out_queue = Queue()

    p = Thread(target=sim_io, args=(out_queue, 'my_query'))
    p.start()

    for result in iter(out_queue.get, SENTINEL):  # sentinel-value breaks the loop
        print(result)
  • 如果可能的话,请在这里阅读为什么for result in iter(out_queue.get, SENTINEL):while True...break设置更受欢迎。
  • 在这里阅读为什么要if __name__ == '__main__':在所有脚本中使用,尤其是在多处理中。
  • 更多关于-get()用法的信息。


 类似资料:
  • 问题内容: 我做了这样的一个波纹管: 但是当我尝试通过getTemp使用temp时我得到0 我只想使用我在线程中所做的计算将其存储在某些变量中以备后用。 问题答案: 或者简单地添加 等待线程完成,然后再获得结果。 您的问题是您试图在计算结果之前获得结果。您应该等待线程完成后才能获得结果。这个答案也许不是最好的,但是是最简单的。由于其他人已经在使用Executors课程,所以我不想重复他们的答案。但

  • 问题内容: 我如何获得一个线程以将元组或我选择的任何值返回给Python中的父级? 问题答案: 我建议您在启动线程之前实例化Queue.Queue,并将其作为线程的args之一传递:在线程完成之前,它将结果作为参数接收到的队列中。父母可以或愿意。 队列通常是在Python中安排线程同步和通信的最佳方法:队列本质上是线程安全的消息传递工具,这是组织多任务的最佳方法!

  • 问题内容: 在android中,我正在创建用于url连接的线程。在线程中,我将响应消息存储在全局声明的字符串中。当我访问method方法时,它返回null。 当我调用该方法时,它返回null。 问题答案: 您真的只想使用它,尝试一下

  • 问题内容: 我有一个方法。值在内部被更改,我想将其返回给该方法。有没有办法做到这一点? 问题答案: 可以使用局部最终变量数组。该变量必须是非基本类型,因此可以使用数组。你还需要同步两个线程,例如使用CountDownLatch: 你也可以这样使用an Executor和a Callable:

  • 问题内容: 我有一个如下的Java线程: 我大约有300个ID,每隔几秒钟-我启动线程以对每个ID进行呼叫。例如。 现在,我想从每个线程收集结果,并批量插入数据库,而不是每2秒进行300次数据库插入。 知道我该如何做到吗? 问题答案: 如果要在执行数据库更新之前收集所有结果,则可以使用该方法。如daveb建议的那样,如果您一次提交一项任务,则可以完成簿记工作。

  • 问题内容: 我的android类中有以下线程。我如何从线程中获取err的值??? 我希望该值是方法的返回值,但是对于我一生来说,我无法获得该值… 问题答案: 您可以通过两种方式实现这一目标。 在 糟糕的 方式。创建一个可变对象,如整数 列表 ,然后让Thread(可运行)写入列表。您可以在外部类/方法的列表中访问值。 使用而不是。一个可以返回值

  • 问题内容: 下面的函数返回一个字符串。我如何获取从线程目标返回的值? 上面显示的“一种显而易见的方法”不起作用:。 问题答案: 我见过的一种方法是将可变对象(例如列表或字典)与索引或某种其他标识符一起传递给线程的构造函数。然后,线程可以将其结果存储在该对象的专用插槽中。例如: 如果你确实想join()返回被调用函数的返回值,则可以使用如下所示的Thread子类来实现: 由于名称修改,这有点麻烦,并

  • 我有一个方法: 当包括睡眠和锁时,我得到: 不过,如果我注释所有锁和,它会按照预期工作。我需要锁,因为我正在处理其他线程。完整的代码如下所示:https://godbolt.org/z/7erjrg,因为otput提供的信息不多,所以我很累