gpt4 book ai didi

python - 使用 websocket 直播标准输出和标准输入

转载 作者:太空宇宙 更新时间:2023-11-04 02:59:20 24 4
gpt4 key购买 nike

online compiler这是我的网站,用户可以在其中运行控制台程序。

目前,用户在运行程序之前必须输入程序输入。我正在尝试为该程序构建实时用户输入(希望提供与他们在笔记本电脑上运行程序相同的体验)。

在实现这一目标的研究中,我遇到了使用 websocketstream stdout and stdin 的解决方案。

我的实现

# coding: utf-8
import subprocess
import thread

from tornado.websocket import WebSocketHandler

from nbstreamreader import NonBlockingStreamReader as NBSR


class WSHandler(WebSocketHandler):
def open(self):
self.write_message("connected")
self.app = subprocess.Popen(['sh', 'app/shell.sh'], stdout=subprocess.PIPE, stdin=subprocess.PIPE,
shell=False)
self.nbsr = NBSR(self.app.stdout)
thread.start_new_thread(self.soutput, ())

def on_message(self, incoming):
self.app.stdin.write(incoming)

def on_close(self):
self.write_message("disconnected")

def soutput(self):
while True:
output = self.nbsr.readline(0.1)
# 0.1 secs to let the shell output the result
if not output:
print 'No more data'
break
self.write_message(output)

nbstreamreader.py

from threading import Thread
from Queue import Queue, Empty


class NonBlockingStreamReader:
def __init__(self, stream):
'''
stream: the stream to read from.
Usually a process' stdout or stderr.
'''

self._s = stream
self._q = Queue()

def _populateQueue(stream, queue):
'''
Collect lines from 'stream' and put them in 'quque'.
'''

while True:
line = stream.readline()
if line:
queue.put(line)
else:
raise UnexpectedEndOfStream

self._t = Thread(target=_populateQueue,
args=(self._s, self._q))
self._t.daemon = True
self._t.start() # start collecting lines from the stream

def readline(self, timeout=None):
try:
return self._q.get(block=timeout is not None,
timeout=timeout)
except Empty:
return None


class UnexpectedEndOfStream(Exception): pass

shell.sh

#!/usr/bin/env bash
echo "hello world"
echo "hello world"
read -p "Your first name: " fname
read -p "Your last name: " lname
echo "Hello $fname $lname ! I am learning how to create shell scripts"

此代码流式传输 stdout 直到 shell.sh 代码到达读取语句。

请指导我做错了什么。为什么它不等待 stdin 并在程序执行完成之前打印“No more data”?

测试它的源代码https://github.com/mryogesh/streamconsole.git

最佳答案

您的 readline() 方法超时,除非您在 100 毫秒内发送输入,然后中断循环。您看不到 read -p 提示的原因是缓冲(因为 readline 和管道缓冲)。最后,您的示例 javascript 不会发送尾随换行符,因此 read 不会返回。

如果增加超时,包括一个换行符和find a way to work around buffering issues ,您的示例基本上应该有效。

我也会使用 tornado.process和协程而不是子进程和线程:

from tornado import gen
from tornado.process import Subprocess
from tornado.ioloop import IOLoop
from tornado.iostream import StreamClosedError
from tornado.websocket import WebSocketHandler


class WSHandler(WebSocketHandler):
def open(self):
self.app = Subprocess(['script', '-q', 'sh', 'app/shell.sh'], stdout=Subprocess.STREAM, stdin=Subprocess.STREAM)
IOLoop.current().spawn_callback(self.stream_output)

def on_message(self, incoming):
self.app.stdin.write(incoming.encode('utf-8'))

@gen.coroutine
def stream_output(self):
try:
while True:
line = yield self.app.stdout.read_bytes(1000, partial=True)
self.write_message(line.decode('utf-8'))
except StreamClosedError:
pass

关于python - 使用 websocket 直播标准输出和标准输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41431882/

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