我正在尝试在树莓派上编写套接字服务器代码。我正在尝试使用装饰器将客户端连接到服务器(这将是我的树莓派)。但是我的代码不断抛出NoneType错误。我对异步装饰器有些陌生,需要一些帮助。您能否看到我的错误出处,请更正我的代码?我将在下面列出我的代码和错误消息。
我的错误讯息:
C:\Users\####\AppData\Local\Programs\Python\Python36-32\python.exe C:/Users/#####/Desktop/autorank/server/client.py
Traceback (most recent call last):
File "C:/Users/#####/Desktop/autorank/server/client.py", line 5, in <module>
@client.connection(("192.168.0.11", 56500))
TypeError: 'NoneType' object is not callable
我的客户代码包:import socket, asyncio
class Client:
def __init__(self):
self.s = None
self.data = None
def connection(self, addr):
"""An asynchronous decorator for any server mainloop. Just decorate it with this and add a Client parameter."""
def wrapper1(func):
async def wrapper2(*args):
self.connect(addr)
await func(self)
self.close_conn()
return await func(self)
return wrapper2
async def connect(self, addr):
"""Connects to the desired server. You can make a server mainloop with the connection decorator."""
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.s.connect(addr)
self.addr = addr
print(f"Connected to {addr}")
async def close_conn(self):
"""Closes connection with the address connected to."""
self.s.close()
print(f"Disconnected from {self.addr}")
del self.addr
async def send_bytes(self, bytes_data):
"""Sends bytedata through a pipe to connected address"""
self.s.sendall(bytes_data)
print(f"Sent {bytes_data.decode()} in bytedata format to {self.addr}")
async def recv(self, buf_size):
"""Recieves data from a server in bytedata format"""
self.data = self.s.recv(buf_size)
最后,我的main.py:import asyncserver
client = asyncserver.Client()
@client.connection(("192.168.0.11", 56500))
def mainloop(cli):
cli.send_bytes(b'Hello!!')
cli.recv(1024)
print(cli.data.decode())
请说我是否应该改善我的问题,我们将不胜感激!
最佳答案
connection
装饰器正确定义了wrapper1
,但未能返回它。它隐式返回None
,这就是在顶层用作mainloop
的结果,从而导致错误。
请注意,wrapper2
等待func(self)
,这可能会导致另一个错误,即None
无法等待。如果计划等待装饰的函数,则应使其异步(async def mainloop(cli): ...
)或使其返回等待对象。
最后,wrapper2
如果不使用任意*args
,则不应接受。这将导致像mainloop(1, 2, 3)
之类的东西在忽略参数的情况下似乎可以正常工作。通常,接受*args
的包装器的目的是将它们转发给包装的函数。如果您不想要或不需要它,只需使wrapper2
不接受任何参数即可。
关于python - 我的异步装饰器不断返回NoneType错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65365353/