我需要运行monkey.patch_all(),因为我的应用程序中有一个Flask 服务器与ValvePython 库相结合(我收到关于无法切换到其他线程的错误)但是我遇到了一个问题。 我已经在没有 ValvePython 的情况下对此进行了测试,以确保问题不会完全取决于此。
我如何启动服务器:
from gevent import monkey; monkey.patch_all();
if __name__ == "__main__":
# Create PyQt5 app
app = QApplication(sys.argv)
# Flask server
server = Server('Ryder Engine')
# Create the custom window (The initialize function creates all the
# server endpoints dynamically via the add_endpoint function
window = RyderDisplay()
window.initialize(server)
# Run Server
threading.Thread(target=server.run, daemon=True).start()
# Start the app
sys.exit(app.exec())
我的服务器类:
import socket
from flask import Flask, Response, request
from gevent.pywsgi import WSGIServer
class EndpointAction(object):
def __init__(self, action):
self.action = action
self.response = Response(status=200, headers={})
def __call__(self, *args):
self.action(request.get_json())
return self.response
class Server(object):
def __init__(self, name):
self.app = Flask(name)
def run(self, port=9520):
http_server = WSGIServer(('0.0.0.0', port), self.app)
http_server.serve_forever()
def add_endpoint(self, endpoint=None, endpoint_name=None, handler=None):
self.app.add_url_rule(endpoint, endpoint_name, EndpointAction(handler), methods=['POST'])
绑定端点之一的 PyQt5 应用程序的主页。这是在 Window 对象内实例化的。其余的通过 json 配置文件通过 HomeConfigurationParser 类进行实例化。
class Home(object):
# Class constructor
def __init__(self, window, server : Server):
self._window = window
self._client = Client()
self._server = server
self._client.subscribeToRyderEngine()
server.add_endpoint('/status', 'status', self.newStatus)
# UI Elements
def create_ui(self, path):
# Initialize
path = path + '/config.json'
self._fps, self._ui = HomeConfigurationParser.parse(self._window, self._client, self._server, path)
# Refresher
self._timer = QTimer()
self._timer.timeout.connect(self.update)
self._timer.start(1000 / self._fps)
def newStatus(self, request):
self._status = request
def update(self):
# Update UI
for elem in self._ui:
elem.update(self._status)
# Reset
if self._status is not None:
self._status = None
我的问题是,通过运行 monkey.path_all() 服务器不再处理请求,换句话说,它基本上忽略了所有 add_endpoint 函数调用。服务器端点必须在运行时添加我不能通过函数上面的@ 直接在代码中添加它们。
为什么会发生这种情况,我该如何解决?
编辑:添加了更多代码位。服务器与 PyQt5 接口并行运行。服务器用于接收数据,然后相应地更新PyQt5接口
答案 0 :(得分:1)
Flask 源代码 (here) 中的 add_url_rule
有一个 @setupmethod
装饰器,表示“在处理第一个请求后忽略我”。 (这是 @app.before_first_request
机制的关键部分。)
如果您在一个线程中启动 Flask,然后从另一个线程调用 add_endpoint
,则您的调用线程会与应用的第一个请求竞争。线程安全也存在一些严重的问题,这些问题会引起从 Flask 主线程外部调用对 Flask 内部产生副作用的方法。
在您的位置上,我会重新安排以确保所有 add_endpoint
调用都发生在 server.run
启动应用程序之前。
您可能仍然对monkeypatching 有问题,但我会先解决这个问题。