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

问一下, 用 flask 做了一个接口, 接收请求生成一个 shell 任务,任务执行时间会很长, 所以不等待执行完成直接返回请求. 这个应该怎么实现呢? 有什么好的实践吗?

  •  
  •   aieike ·
    AIEIKE · 2019-09-05 16:24:57 +08:00 · 5018 次点击
    这是一个创建于 1666 天前的主题,其中的信息可能已经有所发展或是发生改变。
    第 1 条附言  ·  2019-09-05 18:09:12 +08:00
    嗯, 已经了解要用到多线程或多进程.
    主要是不知道有没有好的方法在 flask 里生成新的线程执行 shell
    29 条回复    2020-03-30 10:51:51 +08:00
    sidegem
        1
    sidegem  
       2019-09-05 16:28:30 +08:00 via iPhone
    celery ?
    kiwier
        2
    kiwier  
       2019-09-05 16:30:16 +08:00
    发异步任务
    aieike
        3
    aieike  
    OP
       2019-09-05 16:36:26 +08:00
    @sidegem 这是个内部的接口, 只会有一个任务执行, 是不是有更简单的方法
    aieike
        4
    aieike  
    OP
       2019-09-05 16:36:38 +08:00
    @kiwier 这是个内部的接口, 只会有一个任务执行, 是不是有更简单的方法
    daocheng
        5
    daocheng  
       2019-09-05 16:39:03 +08:00
    有,ThreadPoolExecutor
    ipwx
        6
    ipwx  
       2019-09-05 16:41:46 +08:00 via Android
    你这需求建议用 SimpleHTTPServer 加 threading mixin 不要用 flask
    brucedone
        7
    brucedone  
       2019-09-05 16:43:55 +08:00
    用 Process 这个类就可以啦
    fifa666
        8
    fifa666  
       2019-09-05 16:45:07 +08:00
    可以用 threading 库啊,用别的线程去执行生成 shell 的代码。
    xpresslink
        9
    xpresslink  
       2019-09-05 16:46:11 +08:00
    在数据库里面放 2 个表
    1 任务表,任务 ID + 任务结果
    2 用户消息表
    用户请求来了
    先在任务表创建一个任务记录拿到任务 ID
    开个线程去后台执行 shell 把任务 id 传过去,以便任务完成后按任务 id 把结果填回 任务表,
    给用户消息表插条消息,放个链接用任务 id 去任务临时表取结果。
    aieike
        10
    aieike  
    OP
       2019-09-05 17:14:44 +08:00
    subprocess 可以生成一个新的进程执行 shell 吗
    SmartKeyerror
        11
    SmartKeyerror  
       2019-09-05 17:24:48 +08:00 via Android
    线程或者进程开出去不就行了
    LightLolo
        12
    LightLolo  
       2019-09-05 17:30:10 +08:00
    创建一个新的线程去执行 shell 任务,当前线程返回执行完成。
    allenwuli
        13
    allenwuli  
       2019-09-05 17:56:25 +08:00
    我之前也碰到,我用的 django。业务场景跟你差不多,我后来用了类似 8 楼的方法。我单独开了个进程去查询数据库,没有想到其他的方法。
    misaka19000
        14
    misaka19000  
       2019-09-05 18:09:45 +08:00
    开个新线程不就可以了,问题在哪?
    lolizeppelin
        15
    lolizeppelin  
       2019-09-05 18:59:08 +08:00 via Android
    不要开线程去 直接 fork 两次 exec 就完事
    你又不关心执行结果 不要开线程
    aieike
        16
    aieike  
    OP
       2019-09-05 19:35:30 +08:00
    @lolizeppelin 能说具体些吗?我没太懂, 怎么 fork 两次 exec
    labulaka521
        17
    labulaka521  
       2019-09-05 20:09:29 +08:00
    flask_rq2 可以说很简单了
    clino
        18
    clino  
       2019-09-05 20:23:26 +08:00 via Android
    用 jenkins 调用
    aneureka
        19
    aneureka  
       2019-09-05 21:29:29 +08:00 via Android
    @clino 用 rq,轻量级的很好用
    aneureka
        20
    aneureka  
       2019-09-05 21:30:02 +08:00 via Android
    @clino 不好意思,我莫名其妙就回复到你了…
    lolizeppelin
        21
    lolizeppelin  
       2019-09-05 21:42:47 +08:00
    @aieike

    自己 google 一下
    你执行的 shell 函数,最终实现是 fork 了一次,阻塞 wait,所以卡住
    改成 fork 两次,直接 os._exit(0), 给 pid 1 接管你的子进程就是
    这和写守护进程的原理是一样的

    所有的外部进程调用都是 fork exec 的组合,这是 linux 编程基础,只盯着 python 自然一头雾水
    tfdetang
        22
    tfdetang  
       2019-09-06 10:06:06 +08:00
    from concurrent.futures import ThreadPoolExecutor 这个应该是最简单的解决方案了,随便搜一下就知道怎么用
    aieike
        23
    aieike  
    OP
       2019-09-06 10:26:31 +08:00
    @labulaka521
    @aneureka
    好的我去了解一下这个扩展
    aieike
        24
    aieike  
    OP
       2019-09-06 10:26:54 +08:00
    cigarzh
        25
    cigarzh  
       2019-09-06 14:00:01 +08:00
    fork and exec +1
    wzwwzw
        26
    wzwwzw  
       2019-09-06 14:06:33 +08:00
    subprocess.Popen
    x66
        27
    x66  
       2019-09-06 14:40:34 +08:00
    subprocess.Popen('/path/shell.sh')
    ytymf
        28
    ytymf  
       2019-09-06 15:56:18 +08:00
    任务队列是正道,如果觉得 celery 麻烦,可以试试轻量化的 Huey,redis 默认配置就能跑
    nullboy
        29
    nullboy  
       2020-03-30 10:51:51 +08:00
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3717 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 10:39 · PVG 18:39 · LAX 03:39 · JFK 06:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.