【发布时间】:2017-05-16 20:36:46
【问题描述】:
online compiler这是我的网站,用户可以在其中运行控制台程序。
目前,用户在运行程序之前必须输入程序输入。我正在尝试为程序构建实时用户输入(希望提供与他们在笔记本电脑上运行程序相同的体验)。
为了实现这一目标,我发现了一个使用 websocket 来流式传输标准输出和标准输入 的解决方案。
我的实现
# 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"
此代码流标准输出直到 shell.sh 代码到达读取语句。
请指导我做错了什么。为什么它不等待标准输入并在完成程序执行之前打印“没有更多数据”?
【问题讨论】:
-
您尝试调试您的代码吗? :)
-
是的。它在 on_message 方法内部,在 thread.start_new_thread(self.soutput, ()) 这个语句之后我添加了 print 语句,这意味着线程没有被阻塞。
-
当您(在输入后)在“名字”语句中按回车时发生了什么?它只是没有流式传输吗?如果您浏览整个
shell.sh,即使最后一个echo没有流式传输,会发生什么?这个问题让我想起了一些事情(大约一年前我确实这样做了,syso 通过 websocket 流式传输,但目前我无法访问该代码;但我记得也有过早终止流的问题)。 -
流在到达 read 语句时立即终止。输出是“hello world\nhello world”
-
我已经在github上上传了代码github.com/mryogesh/streamconsole.git。如果您需要测试代码。
标签: python python-2.7 websocket