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
among
V2EX  ›  Python

使用 Python 动态执行主程序外的 py 文件时(支持自定义 scprit)时遇到的 reload 问题(importlib)

  •  
  •   among · 2020-12-07 21:22:53 +08:00 · 1595 次点击
    这是一个创建于 1451 天前的主题,其中的信息可能已经有所发展或是发生改变。
    一个 flask 的应用,需要支持用户自定义的 script 脚本,脚本也是 py 的。
    自定义的 py 脚本经常会改,但是 flask 不能经常重启,当前使用的方式为:


    trigger = importlib.import_module(TS_NAME)
    importlib.reload(trigger)
    sc_res = trigger.check(*TS_ARGS, **self.kwargs)


    外部的 script 中,默认有个 check 的 方法,只需要执行这个方法。

    现在遇到的问题包括:
    1:需要 sys.path.append(LIB_PATH),LIB_PATH 为自定义脚本所在目录,要不然找不到;
    2:使用 import_module 来 import,是根据文件名来 import, 为了防止修改,每次都 reload ;
    3:lib 的顺序问题,因为是根据 name 来 import,如果 2 个自定义脚本的路径不一样,但是 name 一样,就会导致顺序问具体,永远执行的是在 lib 中最靠前的那个,会引起不可预料的问题;
    4:一旦有个用户在里面写 exit(),那 flask 的主程序也就挂了。


    目前虽然可以规避,但并不是一个安全可控的解决方案,设计这个主要的目的是为了实现,可以让用户自定义 script,进行整个系统的定制和二次开发。

    不知道有没有其他好的解决方案,可以在保证灵活性的基础上,又能够实现安全可控。
    6 条回复    2020-12-08 12:23:40 +08:00
    ClericPy
        1
    ClericPy  
       2020-12-07 22:00:25 +08:00
    公司文化全程拒绝服务走离线工具, 所以最近也折腾类似的, 软件工具都带着依赖被我打包成 pyz 单文件丢在 nas 挂盘直接导入了, 结果遇到 reload 当场翻车

    然后工作全用 typed 或者 fire 做成命令行版本调用了(stdout / stdin)... 总算能跑通了, 至于优化什么的, 还是不去过度设计了, 又不是做艺术品, 能跑就得了
    no1xsyzy
        2
    no1xsyzy  
       2020-12-07 22:15:18 +08:00
    用多进程呢?开个工作进程跑用户脚本得到 trigger module 对象,然后把参数传过去调用执行,结果传回。
    fasionchan
        3
    fasionchan  
       2020-12-08 08:52:05 +08:00
    关于第一、二、三点,可以尝试自行将自定义脚本内容读入、编译、然后执行,得到你想要的 check 方法,不需要依赖 import 机制。具体做法可以参考我写的文章: https://www.imooc.com/read/76/article/1918

    关于第四点,二次开发本来就要对系统的安全性负责,做好用户隔离即可。用户隔离要最好做到系统级别的隔离,进程级别的隔离是不够的:如果一个用户执行了关机指令,另一个用户躺着中枪?
    hahaba
        4
    hahaba  
       2020-12-08 09:26:14 +08:00
    最好用线程去处理,子线程死掉,不会影响父线程
    krixaar
        5
    krixaar  
       2020-12-08 09:57:45 +08:00
    搞成跨进程通信(再来个 flask 然后 request 疯狂 post ),或者集成个 Lupa 然后让用户写 lua 脚本,你这边做个控制台给每个脚本安优先级数字,跑的时候按优先级来。
    kaneg
        6
    kaneg  
       2020-12-08 12:23:40 +08:00 via iPhone
    这个程序是跑在你们的服务器还是用户自己的?
    如果是你们的,如果运行环境不做隔离或者限制,用户的代码可以做很多危险的事,比如获取系统敏感信息,删除文件等。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3664 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 10:39 · PVG 18:39 · LAX 02:39 · JFK 05:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.