基於tornado的實現的一個非阻塞的stdin

安利一篇我翻譯的國外大牛的神經網絡入門文章

1. 代碼細節

async_std.py

# -*- coding: utf-8 -*-

import sys
import errno

from tornado.util import errno_from_exception
from tornado.iostream import BaseIOStream
from tornado import gen
try:
    from tornado.platform.posix import _set_nonblocking
except ImportError:
    _set_nonblocking = None


_ERRNO_WOULDBLOCK = (errno.EWOULDBLOCK, errno.EAGAIN)


class UnblockStdIOStreamBase(BaseIOStream):
    """std-based `IOStream` implementation.
    """
    def __init__(self, fd, *args, **kwargs):
        self.fd = fd
        _set_nonblocking(fd)
        super(UnblockStdIOStreamBase, self).__init__(*args, **kwargs)

    def fileno(self):
        return self.fd

    def close_fd(self):
        self.fd.close()

    def write_to_fd(self, data):
        return self.fd.write(data)

    def read_from_fd(self):
        try:
            chunk = self.fd.read(self.read_chunk_size)
        except (IOError, OSError) as e:
            if errno_from_exception(e) in _ERRNO_WOULDBLOCK:
                return None
            elif errno_from_exception(e) == errno.EBADF:
                # If the writing half of a pipe is closed, select will
                # report it as readable but reads will fail with EBADF.
                self.close(exc_info=True)
                return None
            else:
                raise
        if not chunk:
            self.close()
            return None
        return chunk


class UnblockStdinStream(UnblockStdIOStreamBase):
    def __init__(self, io_loop):
        super(UnblockStdinStream, self).__init__(sys.stdin, io_loop=io_loop)

    @gen.coroutine
    def readline(self):
        ret = yield self.read_until('\n')
        raise gen.Return(ret)

test.py

# -*- coding: utf-8 -*-

import tornado.ioloop
from tornado import gen
from async_std import UnblockStdinStream

ioloop = tornado.ioloop.IOLoop.instance()

_std = UnblockStdinStream(io_loop=ioloop)


@gen.coroutine
def test():
    while True:
        ret = yield _std.readline()
        print(ret)


@gen.coroutine
def test2():
    while True:
        yield gen.sleep(2)
        print('sleep 2s')


ioloop.add_callback(test)
ioloop.add_callback(test2)
ioloop.start()

2. 測試

# python test.py
sleep 2s
sleep 2s
sleep 2s
sleep 2s
sleep 2s
qwwer   -----手動從屏幕輸入
qwwer   -----程序打印結果

sleep 2s
sleep 2s
sleep 2s

另外安利我寫的兩個模塊,歡迎使用或貢獻代碼:

一個命令行版本的zookeeper cli
一個tornado web app框架快速生成工具
歡迎關注我的github

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章