(Python)正确使用greenlets

时间:2017-09-22 10:17:25

标签: python python-2.7 gevent

我有一个远程安装的BeagleBone Black,需要控制测量设备,平移/倾斜云台,上传测量数据,托管telnet服务器,...... 我正在使用Python 2.7 这是我需要编程的第一个项目,因此出现了很多问题。 我最想知道我所做的是否是一种合理的方式来处理我需要的东西,以及为什么某些事情不符合我的想法。

某些模块需要协同工作并共享数据。当telnet用户请求平移/倾斜头的位置时,最好的例子是telnet模块。

据我了解,服务器正在阻止该程序,因此我使用gevent / Greenlets从“main”脚本运行它。 剥离版本:

teln模块

from gevent import monkey; monkey.patch_all()  # patch functions to use gevent
import gevent
import gevent.server
from telnetsrv.green import TelnetHandler, command

__all__ = ["MyTelnetHandler", "start_server"]  # used when module is loaded as "from teln import *"

class MyTelnetHandler(TelnetHandler):
    """Telnet implementation."""

    def writeerror(self, text):
        """Write errors in red, preceded by 'ERROR: '."""
        TelnetHandler.writeerror(self, "\n\x1b[31;5;1mERROR: {}\x1b[0m\n".format(text))

    @command(["exit", "logout", "quit"], hidden=True)
    def dummy(self, params):
        """Disables these commands and get them out of the "help" listing."""
        pass

def start_server():
    """Server constructor, starts server."""
    server = gevent.server.StreamServer(("", 2323), MyTelnetHandler.streamserver_handle)
    print("server created")
    try:
        server.serve_forever()
    finally:
        server.close()
        print("server finished")



"""Main loop"""
if __name__ == "__main__":
    start_server()

主要脚本:

#! /usr/bin/env python
# coding: utf-8
from gevent import monkey; monkey.patch_all()  # patch functions to gevent versions
import gevent
from gevent import Greenlet
import teln  # telnet handler
from time import sleep
from sys import exit

"""Main loop"""
if __name__ == "__main__":
    thread_telnet = Greenlet(teln.start_server)
    print("greenlet created")
    thread_telnet.start()
    print("started")
    sleep(10)
    print("done sleeping")
    i = 1
    try:
        while not thread_telnet.ready():
            print("loop running ({:03d})".format(i))
            i += 1
            sleep(1)
    except KeyboardInterrupt:
        print("interrupted")
        thread_telnet.kill()
        print("killed")
        exit()

最后一个主循环需要运行更多功能。

的问题:

  1. 这是同时运行流程/功能的合理方式吗?

  2. 如何让telnet模块中的函数从第三个模块调用函数,控制头部?

  3. 如何确保头部不受telnet模块以及主脚本(运行某种计划)的控制?

  4. 在teln模块的“def start_server()”函数中,启动和停止服务器时会调用两个打印命令。我没有看到这些出现在终端中。可能会发生什么?

  5. 当我从远程计算机打开一个telnet会话,然后关闭它时,我得到以下输出(程序一直在运行):

    Traceback (most recent call last):
      File "/usr/local/lib/python2.7/dist-packages/gevent/greenlet.py", line 536, in run
        result = self._run(*self.args, **self.kwargs)
      File "/usr/local/lib/python2.7/dist-packages/telnetsrv/telnetsrvlib.py", line 815, in inputcooker
        c = self._inputcooker_getc()
      File "/usr/local/lib/python2.7/dist-packages/telnetsrv/telnetsrvlib.py", line 776, in _inputcooker_getc
        ret = self.sock.recv(20)
      File "/usr/local/lib/python2.7/dist-packages/gevent/_socket2.py", line 283, in recv
        self._wait(self._read_event)
      File "/usr/local/lib/python2.7/dist-packages/gevent/_socket2.py", line 182, in _wait
        self.hub.wait(watcher)
      File "/usr/local/lib/python2.7/dist-packages/gevent/hub.py", line 651, in wait
        result = waiter.get()
      File "/usr/local/lib/python2.7/dist-packages/gevent/hub.py", line 898, in get
        return self.hub.switch()
      File "/usr/local/lib/python2.7/dist-packages/gevent/hub.py", line 630, in switch
        return RawGreenlet.switch(self)
    cancel_wait_ex: [Errno 9] File descriptor was closed in another greenlet
    Fri Sep 22 09:31:12 2017 <Greenlet at 0xb6987bc0L: <bound method MyTelnetHandler.inputcooker of <teln.MyTelnetHandler instance at 0xb69a1c38>>> failed with cancel_wait_ex
    
  6. 在尝试不同的事情以了解greenlet如何工作时,我收到了类似的(“cancel_wait_ex:[Errno 9]文件描述符在另一个greenlet中关闭”)错误消息经常。 我一直在寻找,但无法找到/了解正在发生的事情和我应该做的事情。

    1. 如果在运行greenlet时出现问题,我不会得到指向问题的异常(例如,当我尝试打印整数时),但是上面有类似的错误消息。我怎样才能看到“原始”引发的异常?

0 个答案:

没有答案