从并行运行脚本更新值的最佳方法 - Python

Posted

技术标签:

【中文标题】从并行运行脚本更新值的最佳方法 - Python【英文标题】:Best way to update value from parallel running script - Python 【发布时间】:2019-12-22 21:44:05 【问题描述】:

我有两个 Python 脚本(假设 script_1script_2)。 Script_1 使用subprocess 扫描网络以调用一些例程,并更新某些值。它的更新速度很慢。它也可以在自己的进程上无限期地运行,而不是被调用。 Script_2 有一个执行许多不同动作的主循环,一些动作取决于 script_1 更新的值的最新状态.以下是不应该这样做的方式:

### script_1 ###
from time import sleep
import random

# This could also be an infinitely running
# independent task, updating a file/database/whatever
def tedious_task():
    sleep(10)    # working hard...
    value = random.random() * 10
    return value

### script_2 ###
from script_1 import tedious_task
from time import sleep

while True:
    value = tedious_task()  # waiting...
    if value > 5:
        print("Do something")
    else:
        print("Do something else")

    print("Do other stuff")
    sleep(1)

附带说明,我不关心记录 script_1 的更新值。我只需要最新的值。

我想到了几种不同的实现方式,例如中断/回调、异步、线程、多处理,甚至在文件、数据库等外部位置上写入。但是,它们中的大多数都是矫枉过正和其余的都不理想。

线程是一个潜在的候选者。我很喜欢使用线程,但是我已经阅读了很多关于如果没有正确实现它会如何破坏系统的稳定性,并且我需要这个系统长时间稳定。 “尽可能使用异步 IO;必要时使用线程”,我在某处读到。

Async IO 感觉有点矫枉过正(不如使用数据库),但我可能弄错了。我已经很多年没有使用过异步任务了(而且从来没有在 Python 中使用过),所以我已经忘记了其中的大部分内容。我主要担心的是,由于我只需要返回最后一个值,如果我的主程序由于某种原因变慢,它将导致异步函数的一系列滞后返回。我可能遗漏了什么。

那么,有什么方法可以最好地做到这一点? 这可能会作为基于意见的问题传递,但我真正需要的是基于事实的答案。

【问题讨论】:

如果我理解正确 - script_1 运行了很长时间,然后定期更新/返回一个值,script_2 是由这个值被更新触发的?你想让script_1 回到运行状态,而script_2 也在做这件事吗? script_2 不需要被触发,尽管它可能是一个解决方案。理想的情况是按照自己的节奏读取更新的值。 script_1 应该定期运行,所以是的,它应该重新运行(或者继续运行,以防它不与 script_2 交互)。 【参考方案1】:

对于多处理,如下所示应该可以工作

from multiprocessing import Process, Value
from time import sleep
import random

def producer(v):
    while True:
        sleep(10)    # working hard...
        with v.get_lock():
            v.value = random.random() * 10

def worker(v):
    while True:
        value = v.value
        if value > 5:
            print("Do something")
        else:
            print("Do something else")
        print("Do other stuff")


if __name__ == '__main__':
    v = Value('i', 7)  # See the docs for multiprocessing.Value
    producer_process = Process(target=producer, args=(v,))
    worker_process = Process(target=worker, args=(v,))
    producer_process.start()
    worker_process.start()

【讨论】:

这与我对多处理的想法很接近。但是,worker 似乎在等待q.get() 时被卡住了,这正是我想要避免的。有没有办法在设置q 之前继续?另外,由于我需要最后一个值,当生产者在队列中放入多个值时会发生什么?在这种情况下,堆栈的概念会更合适。 即使值没有改变,您希望工作人员继续循环使用相同的值? 是的,完全正确。或者如果不改变读取相同的值,没关系。 您可以使用 multiprocessing.Value() 在两个进程之间共享一个变量docs.python.org/3/library/… 这似乎有效!在接受你的回答之前,我会阅读更多关于它的信息,以便为其他可能有贡献的人留出时间。谢谢:)

以上是关于从并行运行脚本更新值的最佳方法 - Python的主要内容,如果未能解决你的问题,请参考以下文章

使用 APScheduler 在 python 中进行并行编程的最佳方法是啥?

从主脚本并行运行多个 python 脚本

在 mysql 中存储 python timedelta 值的最佳方法是啥?

在 Python 3 中确定 max_workers 用于多处理的最佳值的好方法是啥?

如何并行运行单个Lua脚本对多个Redis值?

从RabbitMQ队列中读取大量消息的最佳方法是什么?