如何在 python-socketio 服务器中使用自定义装饰器?
How to use custom decorators in python-socketio server?
我想在事件处理程序上使用一些自定义装饰器,以便更舒适地处理会话。
这是我没有自定义装饰器的事件处理程序:
@sio.event
async def test(sid, data):
async with sio.session(sid) as sess:
room_id = sess["room_id"]
print('test', room_id)
await sio.emit("test", {'msg': 'msg'}, room=room_id)
这是我使用自定义装饰器的事件:
import functools
async def sess_decorator(func):
@functools.wraps(func)
async def wrapper(sid, data, *args, **kwargs):
async with sio.session(sid) as sess:
return func(sid, data, sess, *args, **kwargs)
logger.error(f'Failed to get sess.\nsid: {sid}\ndata: {data}')
return wrapper
@sio.event
@sess_decorator
async def test(sid, data, sess):
room_id = sess["room_id"]
print('test', room_id)
await sio.emit("test", {'msg': 'msg'}, room=room_id)
问题是在应用 @sess_decorator
事件后似乎根本没有触发。如果我更改装饰器的顺序,它会在调用我的装饰器之前失败并出现以下回溯:
Traceback (most recent call last):
File "/home/pata/.pyenv/versions/3.7.7/envs/cartel_env/lib/python3.7/site-packages/socketio/asyncio_server.py", line 476, in _handle_event_internal
r = await server._trigger_event(data[0], namespace, sid, *data[1:])
File "/home/pata/.pyenv/versions/3.7.7/envs/cartel_env/lib/python3.7/site-packages/socketio/asyncio_server.py", line 504, in _trigger_event
ret = await self.handlers[namespace][event](*args)
TypeError: test() missing 1 required positional argument: 'sess'
似乎库设计有问题?还有其他方法可以完成相同的逻辑吗?
您在实现装饰器的过程中犯了几个错误:
- 装饰器本身不应该是异步函数
func
参数是原函数,是一个协程,所以应该等待
修复后的装饰器如下所示:
def sess_decorator(func):
@functools.wraps(func)
async def wrapper(sid, data, *args, **kwargs):
async with sio.session(sid) as sess:
return await func(sid, data, sess, *args, **kwargs)
logger.error(f'Failed to get sess.\nsid: {sid}\ndata: {data}')
return wrapper
我想在事件处理程序上使用一些自定义装饰器,以便更舒适地处理会话。
这是我没有自定义装饰器的事件处理程序:
@sio.event
async def test(sid, data):
async with sio.session(sid) as sess:
room_id = sess["room_id"]
print('test', room_id)
await sio.emit("test", {'msg': 'msg'}, room=room_id)
这是我使用自定义装饰器的事件:
import functools
async def sess_decorator(func):
@functools.wraps(func)
async def wrapper(sid, data, *args, **kwargs):
async with sio.session(sid) as sess:
return func(sid, data, sess, *args, **kwargs)
logger.error(f'Failed to get sess.\nsid: {sid}\ndata: {data}')
return wrapper
@sio.event
@sess_decorator
async def test(sid, data, sess):
room_id = sess["room_id"]
print('test', room_id)
await sio.emit("test", {'msg': 'msg'}, room=room_id)
问题是在应用 @sess_decorator
事件后似乎根本没有触发。如果我更改装饰器的顺序,它会在调用我的装饰器之前失败并出现以下回溯:
Traceback (most recent call last):
File "/home/pata/.pyenv/versions/3.7.7/envs/cartel_env/lib/python3.7/site-packages/socketio/asyncio_server.py", line 476, in _handle_event_internal
r = await server._trigger_event(data[0], namespace, sid, *data[1:])
File "/home/pata/.pyenv/versions/3.7.7/envs/cartel_env/lib/python3.7/site-packages/socketio/asyncio_server.py", line 504, in _trigger_event
ret = await self.handlers[namespace][event](*args)
TypeError: test() missing 1 required positional argument: 'sess'
似乎库设计有问题?还有其他方法可以完成相同的逻辑吗?
您在实现装饰器的过程中犯了几个错误:
- 装饰器本身不应该是异步函数
func
参数是原函数,是一个协程,所以应该等待
修复后的装饰器如下所示:
def sess_decorator(func):
@functools.wraps(func)
async def wrapper(sid, data, *args, **kwargs):
async with sio.session(sid) as sess:
return await func(sid, data, sess, *args, **kwargs)
logger.error(f'Failed to get sess.\nsid: {sid}\ndata: {data}')
return wrapper