gevent.StreamServer和非阻塞raw_input()? [英] gevent.StreamServer and non-blocking raw_input()?

查看:102
本文介绍了gevent.StreamServer和非阻塞raw_input()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

出于测试目的,我已经使用gevent.StreamServer编写了一个简单的tcp服务器.为了使我能够向某些客户端发送响应,我需要一种非阻塞的方式来通过raw_input()处理输入,最好不使用线程.

I've written a simple tcp server using gevent.StreamServer for testing purposes. In order for me to send responses to some of the clients, I need a non-blocking way to handle input via raw_input(), preferrably without using threads.

经过一番谷歌搜索后,我偶然发现了这个问题:

After some googling I stumbled across this question: How to make non-blocking raw_input when using eventlet.monkey_patch() and why it block everything, even when executed on another thread?

我已经写了以下内容,它完全符合我的要求,但是我认为有更好的方法.有人可以指出我正确的方向吗?另外,感谢为什么try/except不能捕获KeyboardInterrupt的想法.

I've written the following and it does exactly what I want however I assume there's better approach to it. Could someone point me to the right direction? Also, an idea why the try/except does not catch the KeyboardInterrupt is appreciated.

import select
from gevent.monkey import patch_all
from gevent.server import StreamServer

patch_all(os=True, select=True)

def raw_input(message):
    """ Non-blocking input from stdin. """
    sys.stdout.write(message)

    select.select([sys.stdin], [], [])
    return sys.stdin.readline()

def main():
    """ Run the server, listen for commands """

    server = StreamServer(("0.0.0.0", 6000), handle)
    print "Starting server"
    gevent.signal(signal.SIGTERM, server.close)
    gevent.signal(signal.SIGQUIT, server.close)
    gevent.signal(signal.SIGINT, server.close)

    server.start()
    while True:
        try:
            a = raw_input("")
            if a:
                print "Received %s" % a
            gevent.sleep(0)
        except KeyboardInterrupt:
            print "Received a shutdown signal, going down ..."
            server.stop()
            sys.exit(0)

if __name__ == "__main__":
    main()

我已经重写了部分代码,现在我了解了main()函数的愚蠢性.我会将其发布为编辑内容,以防有人偶然发现此问题并对如何操作有更好的想法.

I've rewritten parts of the code and I now understand the silliness of the main()-function. I'll post it as an edit in case someone stumbles on this question and has a better idea on how to do it.

from gevent.signal import signal

def get_console_input():
    """ Non-blocking console input to the server """

    select.select([sys.stdin], [], [])
    # There's quite a bit of code here but it is input handling so 
    # for shortness's sake   I've snipped everything and return the line read.
    return sys.stdin.readline()

def exit(server):
    """ Quit the server gracefully """

    print "Received shutdown signal, going down. """
    server.close()
    sys.exit(0)

def main():
    """ The main function. Create and run the server, listen for commands and
   append any command to the server so it can send them on to the clients """

    # Myserver is a class which inherits from gevent.server.StreamServer.
    # Myserver could just as well be replaced by gevent.server.StreamServer.

    server = MyServer(("0.0.0.0", PORT))
    print "Starting server"

    # Add some signal handlers to quit the server gracefully.
    gevent.signal(signal.SIGTERM, exit, server)
    gevent.signal(signal.SIGQUIT, exit, server)
    gevent.signal(signal.SIGINT, exit, server)

    # Server started in async mode
    server.start()

    while True:
        get_console_input()
        gevent.sleep(0)

if __name__ == "__main__":
    main()

推荐答案

我发现最简单的方法是使用

The simplest way I've found to do this is to use gevent.socket.wait_read to wait until sys.stdin can be read:

wait_read(sys.stdin.fileno())
return sys.stdin.readline()

我还围绕文件描述符编写了一个小的包装,以使它们具有非阻塞的.read().write()方法:

I've also written a small wrapper around file descriptors to give them non-blocking .read() and .write() methods: https://gist.github.com/2915875

这篇关于gevent.StreamServer和非阻塞raw_input()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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