2016-12-06 20 views
0

私はデコレータを使ってSLOCを減らそうとしています。私は、4つのTCPサーバーを起動し、接続するクライアントをグローバル変数として保存する必要がある場合があります。ここにコードがあります。pythonでデコレータを使ってグローバル変数を設定する

# 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

理由だけsocket0_reply'、関数のグローバルとして '' socket0_client'宣言しない代わりに、クライアントに設定されていますか? – Skycc

+0

です。そのコードは、ソケットからデータを受信するまで呼び出されないためです。私は、データが受信される前であってもソケットを他の場所で使用できるようにしたい。 – jrk0414

答えて

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) 
+0

この場合は動作しないようです。クライアントに設定する前に 'global global_client_var'という行を追加すると、コード内のどこにでも 'None'という値が残っています。 – jrk0414

+0

サンプルコードを誤解しました。 Pythonの関数呼び出しでは、すべての引数が値渡しされ、変数がバインドされている参照の更新には使用できません。しかし、コレクションに値を追加できるリストや辞書のようなものを渡すことができます。 – joemeilinger

+0

辞書であればこれはうまくいくでしょう。問題は、どのソケットがどのソケットに属しているのかを知る必要があり、appendメソッドでは追跡できないことです。 – jrk0414

関連する問題