【问题标题】:Python asynchronous call that updates a variable更新变量的 Python 异步调用
【发布时间】:2022-01-02 13:17:32
【问题描述】:

我有一个函数def act(obs),它返回一个浮点数并且计算量很大(需要一些时间来运行)。

import time
import random

def act(obs):
    time.sleep(5) # mimic computation time
    action = random.random()
    return action

我经常在脚本中调用这个函数,比它执行所需的时间要快。调用函数时我不希望有任何等待时间。相反,我更喜欢使用早期计算的返回值。我如何做到这一点?

我想到的是在函数中更新了一个全局变量,我一直在读取全局变量,尽管我不确定这是否是实现它的最佳方法。

【问题讨论】:

    标签: python multithreading asynchronous python-multithreading


    【解决方案1】:

    这是我最终使用的基于this answer

    class MyClass:
        def __init__(self):
            self.is_updating = False
            self.result = -1
        
        def _act(self, obs):
            self.is_updating = True
            time.sleep(5)
            self.result = obs
            self.is_updating = False
            
        def act(self, obs):
            if not self.is_updating:
                threading.Thread(target=self._act, args=[obs]).start()
            return self.result
    
    agent = MyClass()
    
    i = 0
    while True:
        agent.act(obs=i)
        time.sleep(2)
        print(i, agent.result)
        i += 1
    

    【讨论】:

    • 存在竞争条件和对共享数据的不同步访问。是的,您可以为此使用线程,但不,这并不容易。首先,记录下这个东西提供了什么保证,因为只有这样你才能真正推断这是否有效。此外,注入封装的函数会有所帮助,既可以使其更普遍有用,又可以允许对其进行单独测试。
    • “注入包装函数会有所帮助”这是什么意思?如果可能,请链接一个示例:)
    • 我的意思是把它传递给构造函数。研究术语“依赖注入”以获得更多灵感。另外,你可以把它变成一个 Python 装饰器。
    【解决方案2】:

    全局变量方式应该可以工作,你也可以有一个类,它有一个私有成员,比如说result 和一个标志isComputing 和一个方法getResult,它将调用一个方法compute()(通过一个线程) 如果当前没有计算,则返回之前的结果。 compute() 方法应该正确更新标志 isComputing。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-22
      • 2022-11-14
      • 1970-01-01
      • 1970-01-01
      • 2016-06-15
      • 2016-11-11
      • 2011-01-22
      • 1970-01-01
      相关资源
      最近更新 更多