Python Quart 无法关闭后台任务
Python Quart Unable to shutdown background task
我正在开发 Python 应用程序,但我正在从 Flask 迁移到 Quart。该应用程序需要一个在应用程序 运行.
期间持续运行的后台任务
当我尝试使用 control-c 停止进程时,线程没有完全关闭,而是处于关闭例程的 while 循环中。
while not self._master_thread_class.shutdown_completed:
if not pro:
print('[DEBUG] Thread is not complete')
pro = True
我已经关注 this Whosebug 问题,但我不知道如何彻底关闭后台线程,所以我希望得到解释,因为 Quart 文档似乎缺少一点。
MasterThread class:
import asyncio
class MasterThread:
def __init__(self, shutdown_requested_event):
self._shutdown_completed = False
self._shutdown_requested_event = shutdown_requested_event
self._shutdown_requested = False
def __del__(self):
print('Thread was deleted')
def run(self, loop) -> None:
asyncio.set_event_loop(loop)
loop.run_until_complete(self._async_entrypoint())
@asyncio.coroutine
def _async_entrypoint(self) -> None:
while not self. _shutdown_requested and \
not self._shutdown_requested_event.isSet():
#print('_main_loop()')
pass
if self._shutdown_requested_event.wait(0.1):
self. _shutdown_requested = True
print('[DEBUG] thread has completed....')
self._shutdown_completed = True
def _main_loop(self) -> None:
print('_main_loop()')
主要应用模块:
import asyncio
import threading
from quart import Quart
from workthr import MasterThread
app = Quart(__name__)
class Service:
def __init__(self):
self._shutdown_thread_event = threading.Event()
self._master_thread = MasterThread(self._shutdown_thread_event)
self._thread = None
def __del__(self):
self.stop()
def start(self):
loop = asyncio.get_event_loop()
self._thread = threading.Thread(target=self._master_thread.run, args=(loop,))
self._thread.start()
return True
def stop(self) -> None:
print('[DEBUG] Stop signal caught...')
self._shutdown_thread_event.set()
while not self._master_thread.shutdown_completed:
print('[DEBUG] Thread is not complete')
print('[DEBUG] Thread has completed')
self._shutdown()
def _shutdown(self):
print('Shutting down...')
service = Service()
service.start()
Quart 有 startup and shutdown 方法允许在服务器开始服务之前启动某些东西,并在服务器完成服务时停止。如果你的后台任务主要是 IO 绑定,我建议只使用协程函数而不是线程,
async def background_task():
while True:
...
@app.before_serving
async def startup():
app.background_task = asyncio.ensure_future(background_task())
@app.after_serving
async def shutdown():
app.background_task.cancel() # Or use a variable in the while loop
或者您可以对服务执行相同的操作,
@app.before_serving
async def startup():
service.start()
@app.after_serving
async def shutdown():
service.stop()
我正在开发 Python 应用程序,但我正在从 Flask 迁移到 Quart。该应用程序需要一个在应用程序 运行.
期间持续运行的后台任务当我尝试使用 control-c 停止进程时,线程没有完全关闭,而是处于关闭例程的 while 循环中。
while not self._master_thread_class.shutdown_completed:
if not pro:
print('[DEBUG] Thread is not complete')
pro = True
我已经关注 this Whosebug 问题,但我不知道如何彻底关闭后台线程,所以我希望得到解释,因为 Quart 文档似乎缺少一点。
MasterThread class:
import asyncio
class MasterThread:
def __init__(self, shutdown_requested_event):
self._shutdown_completed = False
self._shutdown_requested_event = shutdown_requested_event
self._shutdown_requested = False
def __del__(self):
print('Thread was deleted')
def run(self, loop) -> None:
asyncio.set_event_loop(loop)
loop.run_until_complete(self._async_entrypoint())
@asyncio.coroutine
def _async_entrypoint(self) -> None:
while not self. _shutdown_requested and \
not self._shutdown_requested_event.isSet():
#print('_main_loop()')
pass
if self._shutdown_requested_event.wait(0.1):
self. _shutdown_requested = True
print('[DEBUG] thread has completed....')
self._shutdown_completed = True
def _main_loop(self) -> None:
print('_main_loop()')
主要应用模块:
import asyncio
import threading
from quart import Quart
from workthr import MasterThread
app = Quart(__name__)
class Service:
def __init__(self):
self._shutdown_thread_event = threading.Event()
self._master_thread = MasterThread(self._shutdown_thread_event)
self._thread = None
def __del__(self):
self.stop()
def start(self):
loop = asyncio.get_event_loop()
self._thread = threading.Thread(target=self._master_thread.run, args=(loop,))
self._thread.start()
return True
def stop(self) -> None:
print('[DEBUG] Stop signal caught...')
self._shutdown_thread_event.set()
while not self._master_thread.shutdown_completed:
print('[DEBUG] Thread is not complete')
print('[DEBUG] Thread has completed')
self._shutdown()
def _shutdown(self):
print('Shutting down...')
service = Service()
service.start()
Quart 有 startup and shutdown 方法允许在服务器开始服务之前启动某些东西,并在服务器完成服务时停止。如果你的后台任务主要是 IO 绑定,我建议只使用协程函数而不是线程,
async def background_task():
while True:
...
@app.before_serving
async def startup():
app.background_task = asyncio.ensure_future(background_task())
@app.after_serving
async def shutdown():
app.background_task.cancel() # Or use a variable in the while loop
或者您可以对服务执行相同的操作,
@app.before_serving
async def startup():
service.start()
@app.after_serving
async def shutdown():
service.stop()