Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x 用于WebSocket通信的Jupyter_Python 3.x_Websocket_Ipython_Ipython Notebook_Jupyter - Fatal编程技术网

Python 3.x 用于WebSocket通信的Jupyter

Python 3.x 用于WebSocket通信的Jupyter,python-3.x,websocket,ipython,ipython-notebook,jupyter,Python 3.x,Websocket,Ipython,Ipython Notebook,Jupyter,我正在开发一个需要WebSockets API的应用程序,并将Jupyter(以前的IPython)笔记本作为一个相对次要的功能进行集成。既然Jupyter已经使用WebSockets进行通信,那么要将它集成为一个通用库来为自己之外的其他WebSockets API提供服务有多困难?或者我最好使用另一个库,比如aiohttp?我正在寻找关于这方面最佳实践的任何建议和提示。谢谢 您可以将WebSocket从主应用程序代理到Jupyter 无论您使用什么技术来服务WebSocket,代理循环都非常相

我正在开发一个需要WebSockets API的应用程序,并将Jupyter(以前的IPython)笔记本作为一个相对次要的功能进行集成。既然Jupyter已经使用WebSockets进行通信,那么要将它集成为一个通用库来为自己之外的其他WebSockets API提供服务有多困难?或者我最好使用另一个库,比如
aiohttp
?我正在寻找关于这方面最佳实践的任何建议和提示。谢谢

您可以将WebSocket从主应用程序代理到Jupyter

无论您使用什么技术来服务WebSocket,代理循环都非常相似(等待消息,将消息向前推)。然而,它将依赖于web服务器,因为Python没有类似于WSGI的WebSocket标准

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

"""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()

嗨,Mikko,谢谢你的回答。事实上,经过一番挖掘,我意识到我的问题并不是我真正想问的。因此,我对在外部应用程序中重用iPython的
comm
对象与前端通信的经验非常好奇。话虽如此,您的答案仍然非常有用,并提供了在过程中出现的其他问题的答案,因此我将接受它并创建一个新问题。