问题描述
$ b 我的代码:
我需要在子进程中启动一个长时间运行的后台进程。 >
我看过很多穷人的并行处理,使用 subprocess.Popen 并让它自由运行,但是这通常会导致僵尸问题,正如你注意到的那样。
一个线程(在这种情况下,没有需要 Popen ,只要使用 call 或 check_call 如果进程失败,想要引发异常)。自从Python 3.5以来, call 或者 check_call (或者 run )等待为了完成这个过程,所以没有僵尸,因为你正在一个线程运行它,你不会被阻止。
import线程
def in_background():
subprocess.call([sleep,10])
@ app.route(/)
def index():
t = threading.Thread(target = in_background)
t.start()
returnhi\\\
$ c $注意:要等待线程完成,你必须使用 t.join()为此,你必须保持对 t 线程对象的引用。
顺便说一下,我猜你的 real 进程不是 sleep ,或者它不是很有用, time.sleep(10)也一样(总是在线程中!)
I need to start a long-running background process with subprocess when someone visits a particular view.
My code:
from flask import Flask import subprocess app = Flask(__name__) @app.route("/") def index(): subprocess.Popen(["sleep", "10"]) return "hi\n" if __name__ == "__main__": app.run(debug=True)This works great, for the most part.
The problem is that when the process (sleep) ends, ps -Af | grep sleep shows it as [sleep] <defunct>.
From what I've read, this is because I still have a reference to the process in flask.
Is there a way to drop this reference after the process exits?
I tried doing g.subprocess = subprocess.Popen(["sleep", "10"]), and waiting for the process to end in @app.after_request(response) so I can use del on it, but this prevents flask from returning the response until the subprocess exits - I need it to return the response before the subprocess exits.
Note:
I need the subprocess.Popen operation to be non-blocking - this is important.
解决方案I've seen a lot of "poor man's parallel processing" using subprocess.Popen and letting it run freely, but that's often leading to zombie problems as you noted.
You could run your process in a thread (in that case, no need for Popen, just use call or check_call if you want to raise an exception if process failed). call or check_call (or run since Python 3.5) waits for the process to complete so no zombies, and since you're running it in a thread you're not blocked.
import threading def in_background(): subprocess.call(["sleep", "10"]) @app.route("/") def index(): t = threading.Thread(target=in_background) t.start() return "hi\n"Note: To wait for thread completion you'd have to use t.join() and for that you'd have to keep a reference on the t thread object.
BTW, I suppose that your real process isn't sleep, or it's not very useful and time.sleep(10) does the same (always in a thread of course!)
这篇关于在烧瓶中停止后台进程而不创建僵尸进程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!