捕获瓶子服务器错误

mat*_*ts1 4 python long-polling bottle python-2.7

我试图让我的瓶子服务器,以便当游戏中的一个人注销时,每个人都可以立即看到它.当我使用长轮询时,会向所有用户打开请求.

我遇到问题的一点是捕获当用户从长轮询中离开页面时抛出的异常,该轮询不能再连接到页面.错误消息在这里.

Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/gevent/pywsgi.py", line 438, in handle_one_response
    self.run_application()
  File "/usr/lib/python2.7/dist-packages/gevent/pywsgi.py", line 425, in run_application
    self.process_result()
  File "/usr/lib/python2.7/dist-packages/gevent/pywsgi.py", line 416, in process_result
    self.write(data)
  File "/usr/lib/python2.7/dist-packages/gevent/pywsgi.py", line 373, in write
    self.socket.sendall(msg)
  File "/usr/lib/python2.7/dist-packages/gevent/socket.py", line 509, in sendall
    data_sent += self.send(_get_memory(data, data_sent), flags)
  File "/usr/lib/python2.7/dist-packages/gevent/socket.py", line 483, in send
    return sock.send(data, flags)
error: [Errno 32] Broken pipe
<WSGIServer fileno=3 address=0.0.0.0:8080>: Failed to handle request:
  request = GET /refreshlobby/1 HTTP/1.1 from ('127.0.0.1', 53331)
  application = <bottle.Bottle object at 0x7f9c05672750>

127.0.0.1 - - [2013-07-07 10:59:30] "GET /refreshlobby/1 HTTP/1.1" 200 160 6.038377
Run Code Online (Sandbox Code Playgroud)

处理该页面的功能就是这个.

@route('/refreshlobby/<id>')
def refreshlobby(id):
    while True:
        yield lobby.refresh()
        gevent.sleep(1)
Run Code Online (Sandbox Code Playgroud)

我尝试在函数中捕获异常,并在我用来封装@route的装饰器中,两者都没有用.我尝试制作一个@error(500)装饰器,但也没有触发.这似乎与瓶子的内部有关.

编辑:我现在知道我需要捕获socket.error,但我不知道我的代码在哪里

Tho*_*zco 6

WSGI亚军

仔细观察回溯:这不是在您的函数中发生的,而是在WSGI运行器中.

Traceback (most recent call last):
    File "/usr/lib/python2.7/dist-packages/gevent/pywsgi.py", line 438, in handle_one_response
        self.run_application()
Run Code Online (Sandbox Code Playgroud)

在您的情况下,WSGI运行器的工作方式是:

  1. 收到请求
  2. 从代码中获取部分响应
  3. 将它发送给客户端(这是引发异常的地方)
  4. 重复步骤2-3

你不能抓住这个例外

您的代码中不会引发此错误.

当您尝试向关闭连接的客户端发送响应时,会发生这种情况.

因此,您无法在代码中捕获此错误.

替代解决方案

不幸的是,当它停止被消耗时,不可能从生成器(你的代码)内分辨出来.

依靠你的发电机进行垃圾收集也不是一个好主意.

您还有其他一些解决方案.

"最后一次露面"

另一种知道用户何时断开连接的方法可能是在你的yield陈述之后记录"最后一次见" .

如果最后一次见到的客户端过去,您将能够识别断开连接的客户端.

其他跑步者

另一个非WSGI运行器将更适合实时应用程序.你可以tornado尝试一下.