V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
LeeReamond
V2EX  ›  Python

动态载入, import 之类的有什么轮子吗?

  •  
  •   LeeReamond · 2023-03-11 16:56:21 +08:00 · 2006 次点击
    这是一个创建于 642 天前的主题,其中的信息可能已经有所发展或是发生改变。

    需要实现的效果,比如一个服务在跑,然后服务依赖 n 个插件,插件放在单独一个文件夹里,每一个文件对应一个插件,插件随时可以变化,主体服务希望能不重启直接动态载入新代码这样

    印象里多年前研究过这个功能,是可以实现的,但是好像有些麻烦。有什么现成的轮子吗?

    11 条回复    2023-03-14 09:51:51 +08:00
    noqwerty
        1
    noqwerty  
       2023-03-11 17:04:39 +08:00
    可以直接用 importlib 实现: https://docs.python.org/3/library/importlib.html
    learningman
        2
    learningman  
       2023-03-11 21:10:10 +08:00
    加载用 importlib 是可以搞的,但是清除旧的非常麻烦
    ClericPy
        3
    ClericPy  
       2023-03-11 21:10:25 +08:00
    我刚做了一个类似的...

    假装是个动态脚本的 RPC, 通过 URL route 选择模块路径, 比如类似格式和很多常见模块的 entrypoint 一样, package.module:function 的方式, 传参兼容 params 和 Post form 以及 post JSON 多种方式, 目前参数只支持 kwargs 直接塞函数 **kwargs 里, 之后会根据 inspect 提取函数参数列表来做 validate 相关以及自动生成表单

    然后动态载入刷新代码什么的, 我是每隔一段时间或者用 watchfile 的方式查看文件变化就从 sys.modules 里删掉, 下次导入就是新的代码了, 以前想过太多 reload 的用法, 发现最简单的就是直接删掉旧的...

    这套东西还没时间开源, 难度不大自己琢磨琢磨也就明白了
    LeeReamond
        4
    LeeReamond  
    OP
       2023-03-11 21:44:32 +08:00
    @ClericPy 你的意思是用 insepect 监控代码有没有变化,有就删掉旧的,然后每个插件用某种特定方式命名这种感觉?
    ClericPy
        5
    ClericPy  
       2023-03-11 22:01:25 +08:00   ❤️ 1
    @LeeReamond

    什么啊... inspect 查看函数入参类型的, pydantic 做校验, 类型错误就不执行了

    监控变化用 watchdog 看文件变化, 删掉的逻辑是你只要导入过的模块一般 sys.modules 里面 del 掉, 再导入一次就是新代码了, 不用特定命名, 只要 import path 固定一个目录, 会自动去搜模块名字的. 我那个格式是 URL 路径的格式, 不是命名格式

    如果不放心害怕有篡改文件或者有人偷偷注入什么东西, 我之前还想了做对整个 .py 文件加盐哈希然后哈希值放到文件第一行, 到时候导入前先判断文件对不对
    lolizeppelin
        6
    lolizeppelin  
       2023-03-12 11:50:58 +08:00
    有, openstack 出品 stevedore

    但必须按标准写 python setup.py,生成 egg 文件

    总之就是符合 pkg_resources 那套标准
    lolizeppelin
        7
    lolizeppelin  
       2023-03-12 11:51:42 +08:00
    哦 看错了不好意思...
    featureoverload
        8
    featureoverload  
       2023-03-13 14:21:56 +08:00
    不是有特殊需求的软件,就实现 os.fork+importlib.import_module 好了。这种应该是最简单的
    featureoverload
        9
    featureoverload  
       2023-03-13 14:24:55 +08:00
    @featureoverload 这种应该是最简单的机制了。

    有内存数据(变量 /对象 /数据结构)交换的话,就使用 multiprocessing+importlib.import_module 可以解决。
    LeeReamond
        10
    LeeReamond  
    OP
       2023-03-13 17:32:38 +08:00
    @featureoverload fork 在这里是干什么用的呢
    featureoverload
        11
    featureoverload  
       2023-03-14 09:51:51 +08:00
    @LeeReamond 原本的程序(父进程)负责主 /核心逻辑,比如判断动态导入等。

    在需要动态导入的时候,以及动态导入之后(使用导入的模块)做的事情,在 fork 出来的程序处理。

    这样 [动态导入做的事情] 完成之后,fork 出来的程序(子进程)就让它自己结束--进程销毁;

    ------

    这样就是“业务逻辑”和“核心逻辑”分离,包括进程内的一切变量等等。

    核心逻辑控制什么时候动态导入,业务逻辑实际执行导入和业务行为。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2834 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 12:46 · PVG 20:46 · LAX 04:46 · JFK 07:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.