当前位置: 代码迷 >> python >> 可以读取但不能分配给列表-UnboundLocalError:分配前已引用局部变量'CLIENT_LIST'
  详细解决方案

可以读取但不能分配给列表-UnboundLocalError:分配前已引用局部变量'CLIENT_LIST'

热度:51   发布时间:2023-07-14 08:47:36.0

server.py

import socket, select, signal, errno, os, sys
from threading import Thread

def broadcast_data (sock, message):
    for socket in CONNECTION_LIST:
        #use:
        #if socket != s and socket != sock:
        #if you want to broadcast to all but sending client and server
        # print sock.getpeername()[1]
        # print CLIENT_LIST[0][1]
        if socket != s:
            try :
                socket.send(message)
            except :
                #broken socket connection may be, chat client pressed ctrl+c for example
                socket.close()
                CONNECTION_LIST.remove(socket)


def handle_cli():
    #process client data
    data = sock.recv(RECV_BUFFER)
    if data == '?':
        broadcast_data(sock, hand_cl(CLIENT_LIST))
    elif data == 'removeme':
        hold = rem_cl(sock.getpeername()[1],CLIENT_LIST)
        CLIENT_LIST = hold
    elif data:
        broadcast_data(sock, "\r" + '<' + str(sock.getpeername()) + '> ' + data)
    else:
        sock.close()
        CONNECTION_LIST.remove(sock)

def hand_inter(signum, frame):
    print hand_cl(CLIENT_LIST)

def hand_qui(signum, frame):
    sys.exit(0)

def hand_cl(cl):
    totstring = "Current clients connected:"
    for c in cl:
        totstring+= " "+str(c)
    totstring+="\n"
    return totstring

def rem_cl(peername,cl):
    cl = [(ip, port) for ip, port in cl if port != peername]
    return cl



if __name__ == "__main__": 
    #keep track of socket descriptors
    signal.signal(signal.SIGINT, hand_inter)
    signal.signal(signal.SIGQUIT, hand_qui)
    CONNECTION_LIST = []
    CLIENT_LIST = []
    RECV_BUFFER = 4096
    HOST = 'localhost'
    PORT = int(sys.argv[1])
    ADDR = (HOST, PORT)
    if len(sys.argv) > 2:
        MAXHOST = int(sys.argv[2])
    else:
        MAXHOST = 2


    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind(ADDR)
    s.listen(MAXHOST)

    #add server socket to the list of readable connections
    CONNECTION_LIST.append(s)

    print "Chat server started on port " + str(PORT)
    while 1:
        #fix for signal interrupt
        while True:
            try:
                read_sockets,write_sockets,error_sockets = select.select(CONNECTION_LIST,[],[])
            except select.error, v:
                if v[0] != errno.EINTR: raise
            else: break

        for sock in read_sockets:
            #if sock in read socks == new s, new connection
            if sock == s:
                sockfd, addr = s.accept()

                conmax = [MAXHOST, len(CONNECTION_LIST)]
                conmax = str(conmax)
                #send maxhost number for comparison
                sockfd.send(conmax)
                CONNECTION_LIST.append(sockfd)
                CLIENT_LIST.append(addr)

                print "Client (%s, %s) connected" % addr
                broadcast_data(sockfd, "[%s:%s] entered room\n" % addr)

            #else it's a message from a pre-connected client
            else:
                Thread(target=handle_cli).start()


    s.close()

目标:每当客户端发送消息“ removeme”时,我都希望CLIENT_LIST从CLIENT_LIST中删除特定的客户端。 方法rem_cl可以正常工作并返回正确的结果,但是当我尝试将CLIENT_LIST重新分配给新的更新列表时,出现错误:

line 26, in handle_cli
    hold = rem_cl(sock.getpeername()[1],CLIENT_LIST)
UnboundLocalError: local variable 'CLIENT_LIST' referenced before assignment

但是,如果删除CLIENT_LIST = hold不会出现任何错误。

如何将CLIENT_LIST重新分配为此新返回的列表?

在函数handle_cli() ,当您尝试将值分配给CLIENT_LIST ,您正在将其分配给局部变量(而不是全局变量)。 为了将该值分配给您在脚本中使用的全局变量CLIENT_LIST ,必须首先使用global语句:

global CLIENT_LIST
CLIENT_LIST = ...

如果没有global不可能分配给global变量

另外, 在python中检查使用“ global”关键字的问题 。

  相关解决方案