问题:
我一直在尝试在烧瓶应用程序中使用多处理库(anaconda-python3)。目标是在单击网页中的某个按钮后异步启动进程。为此,网页按钮会在控制器中触发一个功能:
@module.route('/start_long_process', methods=['POST'])
def start_long_process():
...
# Start process async
p = Process(target=some_function)
p.start()
...
如果我之后通过这样做检查过程是否存活:
print(p.pid)
print(p.is_alive())
返回 pid 和 True 值。
然而,好像这个功能似乎从未真正开始过。不会发生任何打印或简单写入文件命令。当我尝试通过使用不在烧瓶应用程序中的多处理过程来运行同样的功能时,它确实做了预期的事情。
我最喜欢的东西是 Celery 与烧瓶和多线程任务结合使用,但这会带来很多开销。
问题
是否无法从烧瓶控制器功能中启动单独的过程?
答案 0 :(得分:1)
如果您使用的是开发烧瓶服务器,则可以similar方式构建应用程序:
from multiprocessing import Pool
from flask import Flask
app = Flask(__name__)
_pool = None
def wanted_function(x):
# import packages that is used in this function
# do your expensive time consuming process
return x * x
@app.route('/expensive_calc/<int:x>')
def route_expcalc(x):
f = _pool.apply_async(wanted_function, (x,))
r = f.get(timeout=2)
return 'Result is %d' % r
if __name__ == '__main__':
_pool = Pool(processes=4)
try:
# insert production server deployment code
app.run()
except KeyboardInterrupt:
_pool.close()
_pool.join()
然后使用./<script_name>.py
运行它,您将同时收听烧录应用程序和_pool
进程。
但是,如果您打算设置更严肃的解决方案,您可能希望使用支持WSGI的网络服务器。
这样,您的烧瓶应用程序将不会像开发服务器案例那样启动。这样您就无法访问_pool
,因此您应该考虑使用更严格的任务队列,例如Celery
。 Here是所有好的列表,其中一些比Celery
更容易设置和使用。
如果您尝试在Windows上执行此操作,则会遇到困难。
显然,在Windows上启动子进程的方式不同。您可以查看documentation以获取更多信息,但这是重要的一部分:
<强>菌种强>
父进程启动一个新的python解释器进程。 子进程只会继承运行所需的资源 进程对象run()方法。特别是不必要的文件 父进程的描述符和句柄不会被继承。 与使用相比,使用此方法启动流程相当慢 fork或forkserver。
在Unix和Windows上可用。 Windows上的默认值。
<强>叉强>
父进程使用os.fork()来分叉Python解释器。 子进程在开始时实际上与进程完全相同 父进程。父级的所有资源都由子级继承 处理。请注意,安全分叉多线程进程是 有问题的。
仅适用于Unix。 Unix上的默认值。
forkserver
当程序启动并选择forkserver启动时 方法,启动服务器进程。从那时起,每当一个新的 需要进程,父进程连接到服务器和 请求它分叉一个新进程。 fork服务器进程是单一的 因此使用os.fork()是安全的。没有必要 资源是继承的。
在支持传递文件描述符的Unix平台上可用 通过Unix管道。