gpt4 book ai didi

python-3.x - 用于 WebSocket 通信的 Jupyter

转载 作者:行者123 更新时间:2023-12-04 14:31:41 26 4
gpt4 key购买 nike

我正在开发一个应用程序,它需要一个 WebSockets API,并且还将集成 Jupyter(以前的 IPython)笔记本作为一个相对次要的功能。由于 Jupyter 已经使用 WebSockets 进行通信,那么将它集成为一个通用库以单独为其他 WebSockets API 提供服务有多难?还是我最好使用另一个库,例如 aiohttp?我正在寻找有关最佳实践的任何建议和提示。谢谢!

最佳答案

您可以将主应用程序中的 WebSockets 代理到 Jupyter。

无论您使用什么技术来为 WebSockets 提供服务,代理循环都非常相似(等待消息,转发消息)。但是,它将依赖于 Web 服务器,因为 Python 没有类似于 WSGI 的 WebSockets 标准。

我在 pyramid_notebook project 做了一个.在自己的进程中运行 Jupyter 是必须的,因为至少在编写代码时,将 Jupyter 直接嵌入到您的应用程序中是不可行的。我不确定最新版本是否改变了这一点。 Jupyter 本身正在使用 Tornado。

"""UWSGI websocket proxy."""
from urllib.parse import urlparse, urlunparse
import logging
import time

import uwsgi
from pyramid import httpexceptions
from ws4py import WS_VERSION
from ws4py.client import WebSocketBaseClient


#: HTTP headers we need to proxy to upstream websocket server when the Connect: upgrade is performed
CAPTURE_CONNECT_HEADERS = ["sec-websocket-extensions", "sec-websocket-key", "origin"]


logger = logging.getLogger(__name__)


class ProxyClient(WebSocketBaseClient):
"""Proxy between upstream WebSocket server and downstream UWSGI."""

@property
def handshake_headers(self):
"""
List of headers appropriate for the upgrade
handshake.
"""
headers = [
('Host', self.host),
('Connection', 'Upgrade'),
('Upgrade', 'WebSocket'),
('Sec-WebSocket-Key', self.key.decode('utf-8')),
# Origin is proxyed from the downstream server, don't set it twice
# ('Origin', self.url),
('Sec-WebSocket-Version', str(max(WS_VERSION)))
]

if self.protocols:
headers.append(('Sec-WebSocket-Protocol', ','.join(self.protocols)))

if self.extra_headers:
headers.extend(self.extra_headers)

logger.info("Handshake headers: %s", headers)
return headers

def received_message(self, m):
"""Push upstream messages to downstream."""

# TODO: No support for binary messages
m = str(m)
logger.debug("Incoming upstream WS: %s", m)
uwsgi.websocket_send(m)
logger.debug("Send ok")

def handshake_ok(self):
"""
Called when the upgrade handshake has completed
successfully.

Starts the client's thread.
"""
self.run()

def terminate(self):
super(ProxyClient, self).terminate()

def run(self):
"""Combine async uwsgi message loop with ws4py message loop.

TODO: This could do some serious optimizations and behave asynchronously correct instead of just sleep().
"""

self.sock.setblocking(False)
try:
while not self.terminated:
logger.debug("Doing nothing")
time.sleep(0.050)

logger.debug("Asking for downstream msg")
msg = uwsgi.websocket_recv_nb()
if msg:
logger.debug("Incoming downstream WS: %s", msg)
self.send(msg)

s = self.stream

self.opened()

logger.debug("Asking for upstream msg")
try:
bytes = self.sock.recv(self.reading_buffer_size)
if bytes:
self.process(bytes)
except BlockingIOError:
pass

except Exception as e:
logger.exception(e)
finally:
logger.info("Terminating WS proxy loop")
self.terminate()


def serve_websocket(request, port):
"""Start UWSGI websocket loop and proxy."""
env = request.environ

# Send HTTP response 101 Switch Protocol downstream
uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', ''))

# Map the websocket URL to the upstream localhost:4000x Notebook instance
parts = urlparse(request.url)
parts = parts._replace(scheme="ws", netloc="localhost:{}".format(port))
url = urlunparse(parts)

# Proxy initial connection headers
headers = [(header, value) for header, value in request.headers.items() if header.lower() in CAPTURE_CONNECT_HEADERS]

logger.info("Connecting to upstream websockets: %s, headers: %s", url, headers)

ws = ProxyClient(url, headers=headers)
ws.connect()

# TODO: Will complain loudly about already send headers - how to abort?
return httpexceptions.HTTPOk()

关于python-3.x - 用于 WebSocket 通信的 Jupyter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32328392/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com