返回顶部
首页 > 资讯 > 后端开发 > Python >基于Python如何实现配置热加载
  • 313
分享到

基于Python如何实现配置热加载

2023-07-02 16:07:46 313人浏览 独家记忆

Python 官方文档:入门教程 => 点击学习

摘要

本篇内容介绍了“基于python如何实现配置热加载”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!背景由于最近工作需求,需要在已有项目添加一个

本篇内容介绍了“基于python如何实现配置热加载”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

    背景

    由于最近工作需求,需要在已有项目添加一个新功能,实现配置热加载的功能。所谓的配置热加载,也就是说当服务收到配置更新消息之后,我们不用重启服务就可以使用最新的配置去执行任务。

    如何实现

    下面我分别采用多进程、多线程、协程的方式去实现配置热加载。

    使用多进程实现配置热加载

    如果我们代码实现上使用多进程, 主进程1来更新配置并发送指令,任务的调用是进程2,如何实现配置热加载呢?

    使用signal信号量来实现热加载

    基于Python如何实现配置热加载

    当主进程收到配置更新的消息之后(配置读取是如何收到配置更新的消息的? 这里我们暂不讨论), 主进程就向进子程1发送kill信号,子进程1收到kill的信号就退出,之后由信号处理函数来启动一个新的进程,使用最新的配置文件来继续执行任务。

    main 函数

    def main():    # 启动一个进程执行任务    p1 = Process(target=run, args=("p1",))    p1.start()    monitor(p1, run) # 注册信号    processes["case100"] = p1 #将进程pid保存    num = 0     while True: # 模拟获取配置更新        print(            f"{multiprocessing.active_children()=}, count={len(multiprocessing.active_children())}\n")        print(f"{processes=}\n")        sleep(2)        if num == 4:            kill_process(processes["case100"]) # kill 当前进程        if num == 8:            kill_process(processes["case100"]) # kill 当前进程        if num == 12:            kill_process(processes["case100"]) # kill 当前进程        num += 1

    signal_handler 函数

    def signal_handler(process: Process, func, signum, frame):    # print(f"{signum=}")    global counts    if signum == 17:  # 17 is SIGCHILD         # 这个循环是为了忽略SIGTERM发出的信号,避免抢占了主进程发出的SIGCHILD        for signame in [SIGTERM, SIGCHLD, SIGQUIT]:            signal.signal(signame, SIG_DFL)        print("Launch a new process")        p = multiprocessing.Process(target=func, args=(f"p{counts}",))        p.start()        monitor(p, run)        processes["case100"] = p        counts += 1    if signum == 2:        if process.is_alive():            print(f"Kill {process} process")            process.terminate()        signal.signal(SIGCHLD, SIG_IGN)        sys.exit("kill parent process")

    完整代码如下

    #! /usr/local/bin/python3.8from multiprocessing import Processfrom typing import Dictimport signalfrom signal import SIGCHLD, SIGTERM, SIGINT, SIGQUIT, SIG_DFL, SIG_IGNimport multiprocessingfrom multiprocessing import Processfrom typing import Callablefrom data import processesimport sysfrom functools import partialimport timeprocesses: Dict[str, Process] = {}counts = 2def run(process: Process):    while True:        print(f"{process} running...")        time.sleep(1)def kill_process(process: Process):    print(f"kill {process}")    process.terminate()def monitor(process: Process, func: Callable):    for signame in [SIGTERM, SIGCHLD, SIGINT, SIGQUIT]:        # SIGTERM is kill signal.        # No SIGCHILD is not trigger singnal_handler,        # No SIGINT is not handler ctrl+c,        # No SIGQUIT is RuntimeError: reentrant call inside <_io.BufferedWriter name='<stdout>'>        signal.signal(signame, partial(signal_handler, process, func))def signal_handler(process: Process, func, signum, frame):    print(f"{signum=}")    global counts    if signum == 17:  # 17 is SIGTERM        for signame in [SIGTERM, SIGCHLD, SIGQUIT]:            signal.signal(signame, SIG_DFL)        print("Launch a new process")        p = multiprocessing.Process(target=func, args=(f"p{counts}",))        p.start()        monitor(p, run)        processes["case100"] = p        counts += 1    if signum == 2:        if process.is_alive():            print(f"Kill {process} process")            process.terminate()        signal.signal(SIGCHLD, SIG_IGN)        sys.exit("kill parent process")def main():    p1 = Process(target=run, args=("p1",))    p1.start()    monitor(p1, run)    processes["case100"] = p1    num = 0    while True:        print(            f"{multiprocessing.active_children()=}, count={len(multiprocessing.active_children())}\n")        print(f"{processes=}\n")        time.sleep(2)        if num == 4:            kill_process(processes["case100"])        if num == 8:            kill_process(processes["case100"])        if num == 12:            kill_process(processes["case100"])        num += 1if __name__ == '__main__':    main()

    执行结果如下

    multiprocessing.active_children()=[<Process name='Process-1' pid=2533 parent=2532 started>], count=1processes={'case100': <Process name='Process-1' pid=2533 parent=2532 started>}p1 running...p1 running...kill <Process name='Process-1' pid=2533 parent=2532 started>multiprocessing.active_children()=[<Process name='Process-1' pid=2533 parent=2532 started>], count=1processes={'case100': <Process name='Process-1' pid=2533 parent=2532 started>}signum=17Launch a new processp2 running...p2 running...multiprocessing.active_children()=[<Process name='Process-2' pid=2577 parent=2532 started>], count=1processes={'case100': <Process name='Process-2' pid=2577 parent=2532 started>}p2 running...p2 running...multiprocessing.active_children()=[<Process name='Process-2' pid=2577 parent=2532 started>], count=1processes={'case100': <Process name='Process-2' pid=2577 parent=2532 started>}p2 running...p2 running...multiprocessing.active_children()=[<Process name='Process-2' pid=2577 parent=2532 started>], count=1processes={'case100': <Process name='Process-2' pid=2577 parent=2532 started>}p2 running...p2 running...kill <Process name='Process-2' pid=2577 parent=2532 started>signum=17Launch a new proceSSMultiprocessing.active_children()=[<Process name='Process-2' pid=2577 parent=2532 stopped exitcode=-SIGTERM>], count=1processes={'case100': <Process name='Process-3' pid=2675 parent=2532 started>}p3 running...p3 running...multiprocessing.active_children()=[<Process name='Process-3' pid=2675 parent=2532 started>], count=1

    总结

    好处:使用信号量可以处理多进程之间通信的问题。

    坏处:代码不好写,写出来代码不好理解。信号量使用必须要很熟悉,不然很容易自己给自己写了一个bug.(所有初学者慎用,老司机除外。)

    还有一点不是特别理解的就是process.terminate() 发送出信号是SIGTERM number是15,但是第一次signal_handler收到信号却是number=17,如果我要去处理15的信号,就会导致前一个进程不能kill掉的问题。欢迎有对信号量比较熟悉的大佬,前来指点迷津,不甚感谢。

    采用multiprocessing.Event 来实现配置热加载

    实现逻辑是主进程1 更新配置并发送指令。进程2启动调度任务。

    这时候当主进程1更新好配置之后,发送指令给进程2,这时候的指令就是用Event一个异步事件通知。

    直接上代码

    scheduler 函数

    def scheduler():    while True:        print('wait message...')        case_configurations = scheduler_notify_queue.get()        print(f"Got case configurations {case_configurations=}...")        task_schedule_event.set() # 设置set之后, is_set 为True        print(f"Schedule will start ...")        while task_schedule_event.is_set(): # is_set 为True的话,那么任务就会一直执行            run(case_configurations)        print("Clearing all scheduling job ...")

    event_scheduler 函数

    def event_scheduler(case_config):    scheduler_notify_queue.put(case_config)    print(f"Put cases config to the Queue ...")    task_schedule_event.clear() # clear之后,is_set 为False    print(f"Clear scheduler jobs ...")    print(f"Schedule job ...")

    完整代码如下

    import multiprocessingimport timescheduler_notify_queue = multiprocessing.Queue()task_schedule_event = multiprocessing.Event()def run(case_configurations: str):    print(f'{case_configurations} running...')    time.sleep(3)def scheduler():    while True:        print('wait message...')        case_configurations = scheduler_notify_queue.get()        print(f"Got case configurations {case_configurations=}...")        task_schedule_event.set()        print(f"Schedule will start ...")        while task_schedule_event.is_set():            run(case_configurations)        print("Clearing all scheduling job ...")def event_scheduler(case_config: str):    scheduler_notify_queue.put(case_config)    print(f"Put cases config to the Queue ...")    task_schedule_event.clear()    print(f"Clear scheduler jobs ...")    print(f"Schedule job ...")def main():    scheduler_notify_queue.put('1')    p = multiprocessing.Process(target=scheduler)    p.start()    count = 1    print(f'{count=}')    while True:        if count == 5:            event_scheduler('100')        if count == 10:            event_scheduler('200')        count += 1        time.sleep(1)if __name__ == '__main__':    main()

    执行结果如下

    wait message...Got case configurations case_configurations='1'...Schedule will start ...1 running...1 running...Put cases config to the Queue ...Clear scheduler jobs ...Schedule job ...Clearing all scheduling job ...wait message...Got case configurations case_configurations='100'...Schedule will start ...100 running...Put cases config to the Queue ...Clear scheduler jobs ...Schedule job ...Clearing all scheduling job ...wait message...Got case configurations case_configurations='200'...Schedule will start ...200 running...200 running...

    总结

    使用Event事件通知,代码不易出错,代码编写少,易读。相比之前信号量的方法,推荐大家多使用这种方式。

    使用多线程或协程的方式,其实和上述实现方式一致。唯一区别就是调用了不同库中,queue和 event.

    # threadingscheduler_notify_queue = queue.Queue()task_schedule_event = threading.Event()# asyncscheduler_notify_queue = asyncio.Queue()task_schedule_event = asyncio.Event()

    “基于Python如何实现配置热加载”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

    --结束END--

    本文标题: 基于Python如何实现配置热加载

    本文链接: https://lsjlt.com/news/343118.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    猜你喜欢
    • 基于Python如何实现配置热加载
      本篇内容介绍了“基于Python如何实现配置热加载”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!背景由于最近工作需求,需要在已有项目添加一个...
      99+
      2023-07-02
    • 基于Python实现配置热加载的方法详解
      目录背景如何实现使用多进程实现配置热加载使用signal信号量来实现热加载采用multiprocessing.Event 来实现配置热加载结语背景 由于最近工作需求,需要在...
      99+
      2024-04-02
    • 基于Cesium如何实现加载显示热力图
      这篇“基于Cesium如何实现加载显示热力图”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“基于Cesium如何实现加载显示热...
      99+
      2023-07-02
    • 基于Cesium实现加载显示热力图
      目录CesiumHeatmap编写案例我是一个小白,到目前为止对于3D方面的东西不是特别的懂,所以说,对于cesium使用的并不是特别的好,可以说根本不会吧,所以说也是在一点一点摸索...
      99+
      2024-04-02
    • Angular4如何实现热加载
      这篇文章将为大家详细讲解有关Angular4如何实现热加载,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。安装插件npm install @angula...
      99+
      2024-04-02
    • 基于vue2如何实现上拉加载功能
      这篇文章主要为大家展示了“基于vue2如何实现上拉加载功能”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“基于vue2如何实现上拉加载功能”这篇文章吧。具体内容如...
      99+
      2024-04-02
    • 如何实现SpringBoot加载配置文件
      这篇文章主要为大家展示了“如何实现SpringBoot加载配置文件”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何实现SpringBoot加载配置文件”这篇文章吧。一、简介在实际的项目开发过程...
      99+
      2023-06-29
    • Spring远程加载配置如何实现
      本篇内容主要讲解“Spring远程加载配置如何实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Spring远程加载配置如何实现”吧!前要本文以携程的Apollo和阿里的Nacos为例。pom中...
      99+
      2023-07-05
    • 基于springMVC web.xml中的配置加载顺序
      目录springMVC web.xml中的配置加载顺序1、Spring上下文环境的配置文件2、SpringMVC配置文件加载顺序是web.xml加载顺序及Spring包扫描注意1、w...
      99+
      2024-04-02
    • webpack如何实现热加载自动刷新
      这篇文章主要介绍webpack如何实现热加载自动刷新,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!具体如下:一、webpack-dev-server 一个轻量级的服务 功能:修改代码...
      99+
      2024-04-02
    • 教你如何基于python实现脚本加密
      这篇文章主要介绍了如何基于python实现脚本加密,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下from pathlib import Pathimport&...
      99+
      2023-06-02
    • 如何使用webpack配置react-hot-loader热加载局部更新
      这篇文章主要讲解了“如何使用webpack配置react-hot-loader热加载局部更新”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何使用webpack配置react-hot-loa...
      99+
      2023-07-05
    • properties配置文件如何利用Java实现加载
      properties配置文件如何利用Java实现加载?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。java加载properties配置文件的六种方法实现代码如下:packa...
      99+
      2023-05-31
      java properties ava
    • 基于OpenCv与JVM如何实现加载保存图像功能
      今天给大家介绍一下基于OpenCv与JVM如何实现加载保存图像功能。,文章的内容小编觉得不错,现在给大家分享一下,觉得有需要的朋友可以了解一下,希望对大家有所帮助,下面跟着小编的思路一起来阅读吧。加载图片openCv有一个名imread的简...
      99+
      2023-06-26
    • 基于Python实现加强版烟花
      上一篇实现的烟花里面预留了很多bug,今天过年,把代码给重新规划了一下。 效果如下: 远处是山和月亮,近处是雪和烟花。 由于忙着吃年夜饭,暂时就不详细解释代码了,空下来了再补上。 ...
      99+
      2024-04-02
    • 基于PHP如何实现微博热搜实时监控平台
      本文小编为大家详细介绍“基于PHP如何实现微博热搜实时监控平台”,内容详细,步骤清晰,细节处理妥当,希望这篇“基于PHP如何实现微博热搜实时监控平台”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。一、整体思路对于搜...
      99+
      2023-07-02
    • MyBatis实现配置加载的步骤
      目录前言正文总结前言 在原始MyBatis的使用中,使用MyBatis时会先读取配置文件mybatis-config.xml为字符流或者字节流,然后通过SqlSessionFacto...
      99+
      2023-05-19
      MyBatis 配置加载
    • Android基于Glide v4.x如何实现图片加载进度监听
      这篇文章主要介绍Android基于Glide v4.x如何实现图片加载进度监听,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!Glide是一款优秀的图片加载框架,简单的配置便可以使用起来,为开发者省下了很多的功夫。不过...
      99+
      2023-05-30
      glide android
    • 基于 PHP 和 Django,如何实现快速加载和响应性能?
      随着互联网的发展,快速加载和响应性能已成为网站开发中不可忽视的重要因素。PHP和Django是两种常用的Web开发框架,它们都提供了很多优秀的特性和工具来帮助我们提高网站的性能和用户体验。本文将介绍如何在PHP和Django中实现快速加载和...
      99+
      2023-08-28
      npm django load
    • android基于dialog实现等待加载框示例
      最近想找一些新颖的等待框,但一直找不到理想的效果,没有办法,只好自己动手丰衣足食了。 先给大家看个效果图! 首先就是新建一个dialog的XML文件了 <?...
      99+
      2022-06-06
      示例 dialog Android
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作