将异步websocket.send()传递给stdout / stderr包装类

时间:2017-02-18 17:58:33

标签: python-3.x websocket async-await python-asyncio

我有一个类函数,它可以解析stdout和stderr,就像这样:

class Unbuffered:
    def __init__(self, stream):
        self.stream = stream
    def write(self, data):
        data = data.strip()
        if data.startswith("INFO: "):
            data = data[6:]
        if '[' in data:
            progress = re.compile(r"\[(\d+)/(\d+)\]")
            data = progress.match(data)
            total = data.group(2)
            current = data.group(1)
            data = '{0}/{1}'.format(current, total)
        if data.startswith("ERROR: "):
            data = data[7:]
        self.stream.write(data + '\n')
        self.stream.flush()
    def __getattr__(self, attr):
        return getattr(self.stream, attr)

当来自websocket的入站到达时,输出来自ProcessPoolExecutor中的函数运行。

我希望输出打印在控制台中以及发送到我的websocket客户端。我尝试了asyncing Unbuffered并将websocket实例传递给它但没有运气。

更新:run()和我的websocket handler()的基本内容如下所示:

def run(url, path):
    logging.addLevelName(25, "INFO")
    fmt = logging.Formatter('%(levelname)s: %(message)s')
    #----
    output.progress_stream = Unbuffered(sys.stderr)
    stream = Unbuffered(sys.stdout)
    #----
    level = logging.INFO
    hdlr = logging.StreamHandler(stream)
    hdlr.setFormatter(fmt)
    log.addHandler(hdlr)
    log.setLevel(level)
    get_media(url, opt)

async def handler(websocket, path):
    while True:
        inbound = json.loads(await websocket.recv())
        if inbound is None:
            break
        url = inbound['url']
        if 'path' in inbound:
            path = inbound['path'].rstrip(os.path.sep) + os.path.sep
        else:
            path = os.path.expanduser("~") + os.path.sep
        # blah more code
        while inbound != None:
            await asyncio.sleep(.001)
            await loop.run_in_executor(None, run, url, path)

run()handler()Unbuffered彼此分开。

1 个答案:

答案 0 :(得分:0)

重写get_media()以使用asyncio而不是在不同的线程中运行它将是最好的。否则,有一些选项可以在常规线程和协同程序之间进行通信,例如,使用socketpair:

import asyncio
import socket
import threading
import time

import random


# threads stuff
def producer(n, writer):
    for i in range(10):
        # print("sending", i)
        writer.send("message #{}.{}\n".format(n, i).encode())
        time.sleep(random.uniform(0.1, 1))


def go(writer):
    threads = [threading.Thread(target=producer, args=(i + 1, writer,))
               for i in range(5)]
    for t in threads:
        t.start()
    for t in threads:
        t.join()
    writer.send("bye\n".encode())


# asyncio coroutines
async def clock():
    for i in range(11):
        print("The time is", i)
        await asyncio.sleep(1)


async def main(reader):
    buffer = ""
    while True:
        buffer += (await loop.sock_recv(reader, 10000)).decode()
        # print(len(buffer))
        while "\n" in buffer:
            msg, _nl, buffer = buffer.partition("\n")
            print("Got", msg)
            if msg == "bye":
                return


reader, writer = socket.socketpair()
reader.setblocking(False)
threading.Thread(target=go, args=(writer,)).start()
# time.sleep(1.5) # socket is buffering
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait([clock(), main(reader)]))
loop.close()

您也可以尝试使用此第三方线程+ asyncio兼容队列:janus