gunicórnio e websockets
Pergunta
Estou tentando conseguir http://www.gelens.org/code/gevent-websocket/ executando e continuo recebendo o seguinte erro.
socket_id=1 already closed.
result = self._run(*self.args, **self.kwargs)
File "/home/walt/virtualenv/ws/local/lib/python2.7/site-packages/gevent/pywsgi.py", line 571, in handle
handler.handle()
File "/home/walt/virtualenv/ws/local/lib/python2.7/site-packages/gevent/pywsgi.py", line 180, in handle
result = self.handle_one_request()
File "/home/walt/virtualenv/ws/local/lib/python2.7/site-packages/gevent/pywsgi.py", line 314, in handle_one_request
self.handle_one_response()
File "/home/walt/virtualenv/ws/local/lib/python2.7/site-packages/geventwebsocket/handler.py", line 26, in handle_one_response
return self._handle_websocket()
File "/home/walt/virtualenv/ws/local/lib/python2.7/site-packages/geventwebsocket/handler.py", line 50, in _handle_websocket
self.log_request()
File "/home/walt/virtualenv/ws/local/lib/python2.7/site-packages/gevent/pywsgi.py", line 394, in log_request
log.write(self.format_request() + '\n')
AttributeError: 'Logger' object has no attribute 'write'
Estou executando o python 2.7.2 no Mint Linux
Solução
Eu recebo esse mesmo bug com gevent-websocket 0.3.4 e gevent 0.13.6 ao executar o gunicorn -k "geventwebsocket.gunicorn.workers.GeventWebSocketWorker" example:app
exemplo.
O problema vem de uma incompatibilidade de expectativas entre gevent e gunicorn.O módulo pywsgi de Gevent espera um objeto logger que implementa um write
método, como objetos de arquivo, stdout, etc.Gunicorn, no entanto, passa em um objeto que tem Registrador métodos (depuração, informação, erro, crítico, aviso, etc).
O código do problema em pywsgi:
def log_request(self):
log = self.server.log
if log:
log.write(self.format_request() + '\n')
Para corrigir isso sozinho, cortei as linhas em um fork do gevent e as alterei para o seguinte:
def log_request(self):
log = self.server.log
if log:
if hasattr(log, "info"):
log.info(self.format_request() + '\n')
else:
log.write(self.format_request() + '\n')
Outras dicas
usou o código do @bkad e adicionou ao arquivo principal do aplicativo
def log_request(self):
log = self.server.log
if log:
if hasattr(log, "info"):
log.info(self.format_request() + '\n')
else:
log.write(self.format_request() + '\n')
import gevent
gevent.pywsgi.WSGIHandler.log_request = log_request
heder para não precisar modificar bibliotecas de terceiros.
Use as versões mais recentes de gevent e gevent-websocket no PyPi.