我试图通过使用装饰器来减少SLOC。我有一个案例,我需要启动四个TCP服务器并将连接客户端保存为全局变量。这是代码。
# The sockets we will be using
socket0_client = None
socket1_client = None
socket2_client = None
socket3_client = None
# Populate them
def save_client(global_client_var):
def decorator(func):
async def inner(client, verbose=False):
global_client_var = client
# Receive stuff
with client:
while True:
# Get data. If there is no data, quit
data = await loop.sock_recv(client, 10000)
if not data:
break
# respond to the data
await func(client, data)
return inner
return decorator
@save_client(socket0_client)
async def socket0_reply(client, data):
await loop.sock_sendall(client, b'Got:'+data)
@save_client(socket1_client)
async def socket1_reply(client, data):
await loop.sock_sendall(client, b'Got:'+data)
@save_client(socket2_client)
async def socket2_reply(client, data):
await loop.sock_sendall(client, b'Got:'+data)
@save_client(socket3_client)
async def socket3_reply(client, data):
await loop.sock_sendall(client, b'Got:'+data)
loop.create_task(tcp_server.single_server(('', 60001), task=socket0_reply, verbose=True))
loop.create_task(tcp_server.single_server(('', 60002), task=socket1_reply, verbose=True))
loop.create_task(tcp_server.single_server(('', 60003), task=socket2_reply, verbose=True))
loop.create_task(tcp_server.single_server(('', 60004), task=socket3_reply, verbose=True))
有一项我没有代码的功能。它是single_server函数。它绑定到给定地址的服务器,等待连接,然后在新连接的客户端上调用任务。
我遇到的问题是虽然客户端填充在内部函数中,并且显然设置为global_client_var,但从不设置全局套接字。他们仍然没有。
这里发生了什么?如何设置这些全局变量?
答案 0 :(得分:0)
您无法更新Python函数参数指向的引用,这是您的代码尝试执行的操作。 Python中的所有函数调用参数都按值传递;但是,在这种情况下,可以将项目附加到传入列表或字典:
sockets = {}
# Populate them
def save_client(global_client_var):
def decorator(func):
async def inner(client, verbose=False):
sockets[global_client_var] = client
# Receive stuff
with client:
while True:
# Get data. If there is no data, quit
data = await loop.sock_recv(client, 10000)
if not data:
break
# respond to the data
await func(client, data)
return inner
return decorator
@save_client(0)
async def socket0_reply(client, data):
await loop.sock_sendall(client, b'Got:'+data)
@save_client(1)
async def socket1_reply(client, data):
await loop.sock_sendall(client, b'Got:'+data)
@save_client(2)
async def socket2_reply(client, data):
await loop.sock_sendall(client, b'Got:'+data)
@save_client(3)
async def socket3_reply(client, data):
await loop.sock_sendall(client, b'Got:'+data)