问题实际上在于Flask的重新加载器。
启用调试模式后,默认情况下,Flask将使用重新加载器 - 一个监视应用程序文件并在服务器更改时重新启动服务器的进程。因此,当Flask运行时 socketio.run line并确定应该启用调试模式 重新运行脚本 。
socketio.run
这意味着您的后台线程将再次启动。但是你已经有一个运行的线程绑定到UDP 127.0.0.1:5005。第二次尝试这样做会失败:
Exception in thread Thread-1: Traceback (most recent call last): File "C:\Users\matejcik\AppData\Local\Programs\Python\Python37\lib\threading.py", line 917, in _bootstrap_inner self.run() File "C:\Users\matejcik\AppData\Local\Programs\Python\Python37\lib\threading.py", line 865, in run self._target(*self._args, **self._kwargs) File ".\app.py", line 23, in background_thread sock.bind((UDP_IP, UDP_PORT)) OSError: [WinError 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted
旧的UDP线程仍然存在,将接收UDP消息并将其打印到控制台。 的 但 强> 该线程在重启之前仍然引用旧的Python环境,因此socketio实例是陈旧的,向void发送消息。
这也是ZMQ收到消息的原因:因为ZMQ订阅不是独占的,旧线程和新线程都可以启动,新线程将能够毫无问题地将消息中继到新的socketio。
通常,线程和重新加载器的交互很混乱,另请参见 https://github.com/miguelgrinberg/Flask-SocketIO/issues/567
如果指定,可以避免此问题 debug=False , 要么 debug=True, use_reloader=False 。
debug=False
debug=True, use_reloader=False