使用 Websockets 从 Python 程序连续输出流 [英] Continuously stream output from program in Python using Websockets

查看:57
本文介绍了使用 Websockets 从 Python 程序连续输出流的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个 websocket,它将不断地将程序的输出流式传输到 HTML 网页.

I would like to create a websocket which will continuosly stream output from the program to the HTML webpage.

我的程序执行的过程需要 2 分钟才能完成,并在执行时记录输出.现在,我的代码每次程序完成执行时都会更新网页,然后立即显示网页上的所有日志.我想不断更新我的网页,即:实时流式传输输出.我的服务器代码如下所示:

Process that my program executes takes 2 minutes to complete and it logs the outputs while it executes. Right now, my code updates the webpage everytime the program finishes executing and then displays all the logs on the webpage at once. I would like to continuosly update my webpage, i.e.: stream the output in realtime. My server code looks like this:

import nest_asyncio
nest_asyncio.apply()
import websockets
import subprocess

async def time(websocket, path):
    while True:
        command = ['myprogram', 'args']
        process = subprocess.Popen(command, stdout=subprocess.PIPE, universal_newlines=True, bufsize=-1)
        now = process.stdout.read()
        await websocket.send(now)

start_server = websockets.serve(time, "127.0.0.1", 5670)

asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

我的客户端看起来像这样:

And my client side looks like this:

<!DOCTYPE html>
<html>
    <head>
        <title>WebSocket</title>
    </head>
    <body>
        <script>
            var ws = new WebSocket("ws://127.0.0.1:5670/"),
                messages = document.createElement('ul');
            ws.onmessage = function (event) {
                var messages = document.getElementsByTagName('ul')[0],
                    message = document.createElement('li'),
                    content = document.createTextNode(event.data);
                message.appendChild(content);
                messages.appendChild(message);
            };
            document.body.appendChild(messages);
        </script>
    </body>
</html>

关于如何做到这一点的任何想法?

Any ideas on how this can be done?

推荐答案

这样做的一种方法是使用 asyncio 的 create_subpocess_exec 命令.此处返回的 Process 实例没有等效的 .poll() 方法,但您仍然可以查询 returncode 属性,只要我们 create_task process.wait()

One way of doing this is to use asyncio's create_subpocess_exec command. The Process instance returned here doesn't have an equivalent .poll() method, but you can still query for the returncode attribute as long as we create_task the process.wait()

import asyncio
import supbrocess


async def time(websocket, path):
    while True:
        command = 'myprogram'
        args = ['a', 'r', 'g', 's']
        process = await asyncio.create_subprocess_exec(command, *args, stdout=subprocess.PIPE)
        asyncio.create_task(process.wait()) # this coroutine sets the return code
        # Must check explicitly for None because successful return codes are usually 0
        while process.returncode is None:
            now = await process.stdout.read()
            if now:
                await websocket.send(now)
            await asyncio.sleep(0) # allow time for the wait task to complete otherwise this coroutine will always be busy
            # see: https://docs.python.org/3/library/asyncio-task.html#sleeping

这篇关于使用 Websockets 从 Python 程序连续输出流的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆