【发布时间】:2020-07-23 00:02:48
【问题描述】:
我扩展了 websocket 回显服务器示例 (here),使其嵌入到 Tkinter 应用程序中。当按下“开始”按钮时,服务器将启动。现在我想在按下“停止”按钮时停止服务器。但是,close() 不起作用。
server.py:
try:
import Tkinter as Tk
from Tkinter import ttk
except ModuleNotFoundError:
import tkinter as Tk
from tkinter import ttk
import asyncio
import websockets
class TkEcho():
def __init__(self):
asyncio.get_event_loop().run_until_complete(self.main())
async def main(self):
'''
Add Buttons
'''
root = Tk.Tk()
Tk.Button(root, text='Start', command=lambda: self.start("localhost", 8765)).grid()
Tk.Button(root, text='Stop', command=self.stop).grid()
await self.run_tk(root)
async def run_tk(self, root, interval=0.05):
'''
Add Tk to asyncio
'''
try:
while True:
root.update()
await asyncio.sleep(interval)
except Tk.TclError as e:
if "application has been destroyed" not in e.args[0]:
raise
async def echo(self, websocket, path):
'''
Receives string and sends it back to sender
'''
string = await websocket.recv()
print(f"recv < {string}")
await websocket.send(string)
print(f"send > {string}")
def start(self, host, port):
'''
Starts websocket
'''
start_server = websockets.serve(self.echo, host, port)
asyncio.ensure_future(start_server)
def stop(self):
'''
Stops websocket
'''
None
if __name__ == "__main__":
t = TkEcho()
client.py:
import asyncio
import websockets
async def send_recv():
uri = "ws://localhost:8765"
async with websockets.connect(uri) as websocket:
string = input("string to send? ")
await websocket.send(string)
print(f"send> {string}")
string = await websocket.recv()
print(f"recv< {string}")
asyncio.get_event_loop().run_until_complete(send_recv())
解决方案:
将TkEcho.__init__ 替换为:
def __init__(self):
loop = asyncio.get_event_loop()
loop.create_task(self.main())
loop.run_forever()
并按如下方式实现TkEcho.stop:
def stop(self):
'''
Stops websocket
'''
asyncio.get_event_loop().stop()
【问题讨论】:
-
你在
stop的定义中尝试过类似asyncio.get_event_loop().stop()的东西吗?这将停止事件循环,并扩展程序的其余部分和服务器。 -
我刚试过。它导致
RuntimeError并使整个应用程序崩溃。它停止了事件循环,但服务器仍在运行:RuntimeError: Event loop stopped before Future completed. -
错误是由于你如何启动事件循环;您可以通过将
__init__中的代码替换为loop = asyncio.get_event_loop(); loop.create_task(self.main()); loop.run_forever()来修复它。
标签: python websocket python-asyncio