问题: 为什么下面的代码使用connect 根据_actions触发对应的函数无法经过装饰器内部的wrapper ,而直接调用的direct却能够经过装饰器内部的wrapper ,请问怎么解决这个问题
- 我确保在程序能够正确的注册send_message到_actions中去。你可以看到我能够调用send_message而不报错
- 我使用的python版本是3.11,操作系统为win10
from functools import wraps
from typing import Callable, Optional
class ActionConsumerMeta(type):
"""
记录操作方法的元类
Metaclass that records action methods
"""
def __new__(mcs, name, bases, attrs):
cls = super().__new__(mcs, name, bases, attrs)
cls._actions = {}
for attr_name, attr_value in attrs.items(): # 函数名、函数
if hasattr(attr_value, "action"):
action_name = attr_value.action
cls._actions[action_name] = attr_name # 返回action对应的函数名 # 这一步是为了以类的方式调用一个独立的action装饰器,这会在元类操作之前,与主要问题没有关系
return cls
data: dict = {
"type": "request",
"action": "message",
"data": {
"message": None,
"additional_info": "Any other info"
},
"from_": "1",
"to": "server",
"request_id": 1
}
websocket = None
channel = '1231'
class GroupChatRoom(metaclass=ActionConsumerMeta):
def action(self, action_name):
def decorator(func):
func.action = (action_name, None)
self._actions[action_name] = func
@wraps(func)
async def wrapper(*args, **kwargs):
print(f"Entering action for action: {action_name}")
return await func(*args, **kwargs)
return wrapper
return decorator
class GroupChatChannelRoom(GroupChatRoom):
async def direct(self):
print(send_message) # <function send_message at 0x00000277CD990900>
await send_message(websocket, channel, data=data)
async def connect(self):
await self._receiver(websocket=websocket, channel=channel)
# async def _receiver(self, websocket: WebSocket, channel: str):
async def _receiver(self, websocket, channel: str):
"""接收信息"""
action = data.get('action')
action_func_or_str: str | Callable = self._actions.get(action)
print(action_func_or_str) # <function send_message at 0x000001D6EF0609A0>
if isinstance(action_func_or_str, str):
await getattr(self, action_func_or_str)(websocket=websocket, channel=channel, data=data)
else:
await action_func_or_str(websocket=websocket, channel=channel, data=data)
group_chatroom = GroupChatChannelRoom()
@group_chatroom.action('message')
async def send_message(websocket, channel: str, data: dict, **kwargs):
print(f"Sending message to channel {channel}: {data.get('message')}")
import asyncio
async def a():
print('connect')
await group_chatroom.connect()
# Sending message to channel 123: None
print('direct')
await group_chatroom.direct()
# Entering action for action: message
# Sending message to channel 1231: None
asyncio.run(a())