如何设置带线程的 bottlepy 以在后台处理
How to set up bottlepy with threading for processing in background
我正在尝试设置一个在后台处理渲染的 Web 服务,这需要一分钟。在渲染过程中,我希望服务器能够并行处理请求,returning Id {} not found
或结果(如果有的话)。
我找到的教程主要处理简单的请求,没有太多处理(http://bottlepy.org/docs/dev/async.html,使用 sleep
来模拟处理)。所以我不太确定如何实现线程 - 是否应该在线程中设置 bottlepy 路由?
来自 http://bottlepy.org/docs/dev/tutorial_app.html#server-setup 我知道 bottlepy 的默认服务器是单线程的,所以我尝试切换到另一个服务器 (PasteServer)。
from bottle import Bottle, run, PasteServer
from service import startWithDirectArgs, default_out, default_out_dir
import threading
class BakingThread(threading.Thread):
# lock = threading.Lock()
isProcessRunning = False
resultDict = {}
currentId = 0
def __init__(self, bakingId: str, args):
super().__init__()
self.bakingId = bakingId
self.args = args
def run(self):
# with BakingThread.lock:
if BakingThread.isProcessRunning:
return False
BakingThread.processRunning = True
print("3[1;32;49m" +
"Starting baking process with id {}".format(self.bakingId) +
"3[0;37;49m")
result = startWithDirectArgs(self.args)
# result = calculatePi(100_0000_00)
BakingThread.resultDict[self.bakingId] = str(result)
BakingThread.isProcessRunning = False
print("3[1;32;49m" +
"Finished baking process with id {}".format(self.bakingId) +
"3[0;37;49m")
return result
def getUniqueId() -> str:
BakingThread.currentId += 1
return str(BakingThread.currentId)
def calculatePi(n: int) -> float:
halfPi = 1.0
zaehler = 2.0
nenner = 1.0
for i in range(n):
halfPi *= zaehler / nenner
if i % 2:
zaehler += 2.0
else:
nenner += 2.0
return 2.0 * halfPi
app = Bottle()
@app.route("/bakeFile/<fileParam>")
def bakeFile(fileParam: str):
# args = {"file": fileParam, "out": default_out_dir + default_out}
args = {
"file": "build/igmodels/AOMaps/Scene.igxc", # fileParam,
"out": default_out_dir + default_out
}
print(args)
cid = getUniqueId()
bt = BakingThread(cid, args)
bt.start()
bt.join()
@app.route("/bakeUrl/<urlParam>")
def bakeUrl(urlParam: str):
args = {"url": urlParam, "out": default_out_dir + default_out}
print(args)
cid = getUniqueId()
bt = BakingThread(cid, args)
bt.start()
bt.join()
@app.route("/pullState/<bakingId>")
def pullState(bakingId: str):
print("3[1;33;49m" + "pullState id {}".format(BakingThread.currentId) +
"3[0;37;49m")
result = BakingThread.resultDict.get(bakingId,
"Id {} not found".format(bakingId))
return result
app.run(host="localhost", port=8080, debug=True, server=PasteServer)
我希望能够 运行 http://localhost:8080/bakeFile/3dGeometryFileName
并且在渲染 运行ning 时我希望调用 http://localhost:8080/pullState/1
以 Id 1 not found
响应。渲染完成后,相同的调用应该 return 结果。
编辑:渲染过程是用 C++ 实现的,与 PyBind 绑定。全局解释器锁 (GIL) 阻止了渲染和网络服务的并发执行,因此我在 C++ 代码中的昂贵计算之前和之后添加了 py::gil_scoped_release release;
和 py::gil_scoped_acquire acquire;
。在上面的代码中,我添加了一个片段来直接在 python 中计算 pi,而无需 C++/PyBind,因此 bottlePy 开发人员可以将我指向 GIL 的东西。 (谢谢马塞尔)
解决了。
渲染过程是用C++实现的,绑定了PyBind。全局解释器锁 (GIL) 阻止了渲染和网络服务的并发执行,因此我在 C++ 代码中的昂贵计算之前和之后添加了 py::gil_scoped_release release;
和 py::gil_scoped_acquire acquire;
。在上面的代码中,我添加了一个片段来直接在 python 中计算 pi,而无需使用 C++/PyBind,因此 bottlePy 开发人员可以将我指向 GIL 的东西。 (谢谢马塞尔)
我正在尝试设置一个在后台处理渲染的 Web 服务,这需要一分钟。在渲染过程中,我希望服务器能够并行处理请求,returning Id {} not found
或结果(如果有的话)。
我找到的教程主要处理简单的请求,没有太多处理(http://bottlepy.org/docs/dev/async.html,使用 sleep
来模拟处理)。所以我不太确定如何实现线程 - 是否应该在线程中设置 bottlepy 路由?
来自 http://bottlepy.org/docs/dev/tutorial_app.html#server-setup 我知道 bottlepy 的默认服务器是单线程的,所以我尝试切换到另一个服务器 (PasteServer)。
from bottle import Bottle, run, PasteServer
from service import startWithDirectArgs, default_out, default_out_dir
import threading
class BakingThread(threading.Thread):
# lock = threading.Lock()
isProcessRunning = False
resultDict = {}
currentId = 0
def __init__(self, bakingId: str, args):
super().__init__()
self.bakingId = bakingId
self.args = args
def run(self):
# with BakingThread.lock:
if BakingThread.isProcessRunning:
return False
BakingThread.processRunning = True
print("3[1;32;49m" +
"Starting baking process with id {}".format(self.bakingId) +
"3[0;37;49m")
result = startWithDirectArgs(self.args)
# result = calculatePi(100_0000_00)
BakingThread.resultDict[self.bakingId] = str(result)
BakingThread.isProcessRunning = False
print("3[1;32;49m" +
"Finished baking process with id {}".format(self.bakingId) +
"3[0;37;49m")
return result
def getUniqueId() -> str:
BakingThread.currentId += 1
return str(BakingThread.currentId)
def calculatePi(n: int) -> float:
halfPi = 1.0
zaehler = 2.0
nenner = 1.0
for i in range(n):
halfPi *= zaehler / nenner
if i % 2:
zaehler += 2.0
else:
nenner += 2.0
return 2.0 * halfPi
app = Bottle()
@app.route("/bakeFile/<fileParam>")
def bakeFile(fileParam: str):
# args = {"file": fileParam, "out": default_out_dir + default_out}
args = {
"file": "build/igmodels/AOMaps/Scene.igxc", # fileParam,
"out": default_out_dir + default_out
}
print(args)
cid = getUniqueId()
bt = BakingThread(cid, args)
bt.start()
bt.join()
@app.route("/bakeUrl/<urlParam>")
def bakeUrl(urlParam: str):
args = {"url": urlParam, "out": default_out_dir + default_out}
print(args)
cid = getUniqueId()
bt = BakingThread(cid, args)
bt.start()
bt.join()
@app.route("/pullState/<bakingId>")
def pullState(bakingId: str):
print("3[1;33;49m" + "pullState id {}".format(BakingThread.currentId) +
"3[0;37;49m")
result = BakingThread.resultDict.get(bakingId,
"Id {} not found".format(bakingId))
return result
app.run(host="localhost", port=8080, debug=True, server=PasteServer)
我希望能够 运行 http://localhost:8080/bakeFile/3dGeometryFileName
并且在渲染 运行ning 时我希望调用 http://localhost:8080/pullState/1
以 Id 1 not found
响应。渲染完成后,相同的调用应该 return 结果。
编辑:渲染过程是用 C++ 实现的,与 PyBind 绑定。全局解释器锁 (GIL) 阻止了渲染和网络服务的并发执行,因此我在 C++ 代码中的昂贵计算之前和之后添加了 py::gil_scoped_release release;
和 py::gil_scoped_acquire acquire;
。在上面的代码中,我添加了一个片段来直接在 python 中计算 pi,而无需 C++/PyBind,因此 bottlePy 开发人员可以将我指向 GIL 的东西。 (谢谢马塞尔)
解决了。
渲染过程是用C++实现的,绑定了PyBind。全局解释器锁 (GIL) 阻止了渲染和网络服务的并发执行,因此我在 C++ 代码中的昂贵计算之前和之后添加了 py::gil_scoped_release release;
和 py::gil_scoped_acquire acquire;
。在上面的代码中,我添加了一个片段来直接在 python 中计算 pi,而无需使用 C++/PyBind,因此 bottlePy 开发人员可以将我指向 GIL 的东西。 (谢谢马塞尔)