Werkzeug BaseWSGIServer线程处理请求后挂起,终端无响应问题求助
这问题卡了我快一周了,啥正事都没法干——要是你有Python/Werkzeug/Flask/多线程相关经验,求帮忙看看...
平时咱们跑Flask应用,都是开个单独终端输入py flask.py,手动启动,再用Ctrl-C手动关停。但我的Python应用只在特定场景下需要这个本地服务器,比如用Spotify的授权码流程获取令牌,之后才能用他们的Web API发有效请求。
我的auth_server.py文件负责这块逻辑,里面有个继承自Thread的LocalServerThread类,是直接抄的八年前的一个Stack Overflow回答——那时候Windows平台下这是唯一能用的方案,但现在看来只能算半残示例了。
先上这个类的完整代码:
from werkzeug.serving import make_server class ServerThread(threading.Thread): THREAD_NAME = 'LocalServerThread' def __init__(self, app): threading.Thread.__init__(self, name=LocalServerThread.THREAD_NAME) self.server = make_server('127.0.0.1', 8080, app) self.ctx = app.app_context() self.ctx.push() def run(self): log.info('starting server') self.server.serve_forever() def shutdown(self): self.server.shutdown() def start_server(): global server app = flask.Flask('myapp') # App routes defined here server = ServerThread(app) server.start() log.info('server started') def stop_server(): global server server.shutdown()
这是auth_server.py里剩下的相关代码:
def start_local_http_server(): app = Flask(__name__) @app.route('/') def home(): @app.route('/login') def login(): @app.route('/callback') def callback(): global server server = LocalServerThread(app) server.start() print(fr'Started {LocalServerThread.THREAD_NAME}, serving: http://127.0.0.1:8080') def stop_local_http_server(): server.shutdown()
这是我main.py里调用这块的实际代码:
if not auth_server.validate_token(reject=True): auth_server.start_local_http_server() time.sleep(4) auth_server.stop_local_http_server() print('Finally Done')
重点来了,问题就出在这...
我用py ./main.py运行程序,如果啥都不干让它自己跑,shutdown能正常工作,服务器也能正确关停,没问题。
但要是在主线程sleep的4秒里,我访问任意路由('/', '/login', '/callback'),服务器成功返回页面后,程序执行到self.server.shutdown()就会卡住,要等90到300秒才会继续走到主线程的print('Finally Done')。这段时间终端就一直僵在那,程序死活不退出:

这真的快把我逼疯了,调试也摸不着头脑。self.server.shutdown()会进到socketserver.py里的BaseServer的shutdown方法,但再往下就没法单步调试了,感觉像是在等什么东西...我把调用栈列出来了:
两种情况的调用栈对比(调试到无法继续前的状态):
左边是正常运行(没访问路由),右边是sleep期间访问了'/':

备注:我用的是Windows系统。
有没有懂行的大佬能看出问题出在哪?这不仅能帮我解决麻烦,估计也能帮到以后遇到同样问题的人...
备注:内容来源于stack exchange,提问作者The-Stanislav

