Catching bottle server errors

放肆的年华 提交于 2019-12-23 12:20:15

问题


I am trying to get my bottle server so that when one person in a game logs out, everyone can immediately see it. As I am using long polling, there is a request open with all the users.

The bit I am having trouble with is catching the exception that is thrown when the user leaves the page from the long polling that can no longer connect to the page. The error message is here.

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

The function to handle that page is this.

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

I tried catching the exception within the function, and in a decorator which I put to wrap @route, neither of which worked. I tried making an @error(500) decorator, but that didn't trigger, either. It seems that this is to do with the internals of bottle.

Edit: I know now that I need to be catching socket.error, but I don't know whereabouts in my code


回答1:


The WSGI runner

Look closely at the traceback: this in not happening in your function, but in the WSGI runner.

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

The way the WSGI runner works, in your case, is:

  1. Receives a request
  2. Gets a partial response from your code
  3. Sends it to the client (this is where the exception is raised)
  4. Repeats steps 2-3

You can't catch this exception

This error is not raised in your code.

It happens when you try to send a response to a client that closed the connection.

You'll therefore not be able to catch this error from within your code.

Alternate solutions

Unfortunately, it's not possible to tell from within the generator (your code) when it stops being consumed.

It's also not a good idea to rely on your generator being garbage collected.

You have a couple other solutions.

"Last seen"

Another way to know when an user disconnects would probably be to record a "last seen", after your yield statement.

You'll be able to identify clients that disconnected if their last seen is far in the past.

Other runner

Another, non-WSGI runner, will be more appropriate for a realtime application. You could give tornado a try.



来源:https://stackoverflow.com/questions/17508415/catching-bottle-server-errors

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!