我需要一些关于python的websockets模块如何工作的见识。我已经掌握了要点,但是有一些我遇到的麻烦。我想先检查一下我的理解,然后问一些具体问题。
顺便说说第一次海报。
我了解websockets(即websockets,而不是websocket)依赖于asyncio,并且我对所有这些如何工作有半点体会。
出于这个问题的目的,无需解释python中的open_browser。
在下面的代码中,我认为这是事件序列。
1)websockets.serve()创建某种服务器对象。 receive_input是要触发的处理函数。
2)asyncio.run_until_complete [(receive_input)]实际上并没有运行服务器,而是将其注册为要在事件循环中触发的东西。不过asyncio和.serve很聪明,并且知道套接字两端都关闭时会关闭循环。 (某种ServerConnectionClosed异常或类似的东西)
3)asyncio.run_forever启动并渗透到事件循环中。 receive_input函数反复触发,直到关闭连接。
4)receive_input函数接受输入。
5)浏览器窗口打开。
6)浏览器窗口关闭。一条消息被发送回python,命令其退出。
7)Python收到quit命令并触发其退出过程。
8)Python退出。
python
import asyncio, json, websockets
open_browser.open()
async def receive_input( web_socket, path ):
web_socket = web_socket #<------ Question #1
async for input_from_javascript in web_socket: await
handle_input( web_socket, input_from_javascript )
async def handle_input( input_from_javascript )
input_from_javascript = json.loads( input_from_javascript );
if input_from_javascript[ 'key' ] == 'on_window_unload':
on_window_unload( input_from_javascript )
def on_window_unload( web_socket, input_from_javascript ):
#Question #2
web_socket.close(); kill(); sys.exit()
def kill( port=9000 ):
Question #4
os.system( 'kill -9 $(lsof -t -i:' + str( port ) + ')' )
kill(); open_browser()
start_server = websockets.serve( receive_input, '0.0.0.0', 9000 )
asyncio.get_event_loop().run_until_complete( start_server )
asyncio.get_event_loop().run_forever()
javascript
var web_socket = null;
window.onload = function( event ) {
web_socket = new WebSocket( 'ws://0.0.0.0:9000' );
}
window.onbeforeunload = function() {
web_socket.send( JSON.stringify( { 'key': 'on_window_unload' } ) );
};
问题1.我需要将web_socket变量定义为全局变量,模块中的其他函数可以访问它而无需将其作为变量传递。我当前的解决方案可以工作,但是效果不是很好。我可以在重复触发的服务函数receive_input之外定义web_socket变量吗?
问题2。我的on_window_unload函数并不总是触发。有时python进程会一直运行。可能的原因是什么?显然,如果我要部署它,就不会有任何内存泄漏。
问题2a:我猜该函数永远不会触发的原因是因为on_window_unload消息以某种方式丢失了。我是否应该构建一个安全功能来每秒检查一次,以查看websocket是否仍在javascript端运行,并在需要时强制关闭?至少通常会采用哪种形式。
问题3:有时我会遇到管道破裂的错误。也许我被告知每20次射击中有一个管道破裂。我希望这是因为在先前的代码触发过程中发生了一个错误,导致退出过程没有触发,因此套接字仍然很忙-因此,当一切都说完了并且代码没有错误时,这不会是个问题。我希望这样做是因为替代方法是websockets本质上是不稳定的,我无法信任它们。
问题4:取消进程。如果我在退出原始进程后过早尝试访问“ 0.0.0.0:9000”,则会遇到“套接字已在使用”错误。这是因为当浏览器关闭时,端口不会立即释放自身。关于在客户端失去连接一秒钟的机会上保持打开状态并保持打开状态以防止必须重新加载页面的事情。这意味着我需要在关闭窗口时显式关闭端口。我知道可以在服务器上使用“ ReuseAddr”(或某物)标志来关闭端口(几乎立即关闭)。基本上,如何立即关闭窗口两端的websocket,以便立即将其用于下一次触发。
问题4a):kill()函数很残酷。这是杀死进程的真正暴力方式。它可以工作,但是我想要的是pythonic的东西,少一点,好一点,残酷的。
我为我的问题模棱两可表示歉意。我已尝试尽可能具体,但实际上,这些是大思想问题,而不是关于特定的代码行。