字典更新内部功能但不在其外部

时间:2016-11-11 11:33:25

标签: python multithreading sockets

我有一个更新字典并打印它的线程(new_client_thread)。 当我尝试再次从主线程打印字典时,字典没有更改。当线程(new_client_thread)再次更改字典时,所有更改也被保存,但只保存在此线程内,而不是在主线内。

这是我的server.py

from threading import Thread
from threading import Lock


def add_client_to_dict(my_id, connect):
    my_socket_list[int(my_id)] = connect
    print my_socket_list


def print_my_socket_list():
    print my_socket_list
    if len(my_socket_list) == 0:
        print "dictionary is empty"
        return None
    for item in my_socket_list:
        print item


def connection_failed(connecting):
    print "deleting"
    for key in my_socket_list.keys():
        if my_socket_list[key] == connecting:
            my_socket_list.pop(key)
            print "deleted"
            connecting.close()
            break


def new_clients():
    from Class import Socket_control
    while True:
        connect = Socket_control.open_socket()
        thread_listener = Thread(target=Socket_control.recv_msg, args=(connect,))
        thread_listener.start()


def menu():
    choice = 1
    while choice != 0:
        choice = raw_input("What would you like to do?\n[0] exit.\n[1] print list of computers.")
        if choice == "1":
            print_my_socket_list()
            if len(my_socket_list) == 0:
                continue
            computer = raw_input("Choose a computer :")
            msg = raw_input("Send message: ")
            my_socket_list[computer].send_message("MSG:" + msg)


def main():

    new_client_thread = Thread(target=new_clients)
    new_client_thread.start()
    menu()

my_socket_list = {}
my_socket_list["0"] = None

if __name__ == "__main__":
    main()

这是我的套接字控件

import socket
import datetime
import server
from mutex import mutex
def open_socket():
    global connect
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.bind(("0.0.0.0", 8200))
    except socket.error:
        print "Socket Error"

    sock.listen(1)
    connect, addr = sock.accept()
    return connect


def recv_msg(connecting):
    while True:
        try:
            data = connecting.recv(1024)
            if len(data) == 0:
                server.connection_failed(connect)
                return None
            print "recv " + data
            data = data.decode('utf-8')
            if data[:4] == "MYID":
                handle_client_id(data[4:])
        except:
            server.connection_failed(connecting)
            print "Recv Error"
            return None




def handle_client_id(data):
    my_id = data
    if my_id == "0":
        my_id = get_last_number()+1
        send_message("MYID" + str(my_id))
    file_writing_new_client(my_id)
    server.add_client_to_dict(my_id,connect)


def send_message(data):
    try:
        print "sent " + data
        connect.send(data)
    except:
        print "Sent Error"
        server.connection_failed(connect)


def get_last_number():
    with open("jennifer_clients_list.txt") as my_file:
        my_file.seek(0)
        first_char = my_file.read(1)
        my_file.seek(0)
        if not first_char:
            return 0
        else:
            lines = my_file.readlines()
            print "text: "
            print lines
            data = lines[-1].split(" ")[0]
            return int(data)

1 个答案:

答案 0 :(得分:1)

在CPython中,你应该在一个线程中更新dict并在另一个线程中访问它时没有问题(参见Using a global dictionary with threads in Python)。

问题的直接原因是您尝试使用错误的密钥引用字典。当您将ID存储在字典中时,您首先将其转换为int,但是当您从主线程访问它时,您正在使用用户提供的str输入;即int('88') '88'相同的密钥。

如果您更改了该行:

my_socket_list[computer].send_message("MSG:" + msg)

为:

my_socket_list[int(computer)].send_message("MSG:" + msg)

您将进入下一个错误(即socket对象没有send_message方法,但如果您将其更改为.send,则会有效。

要回到最初的主题,将代码依赖于CPython的全局解释器锁等实现细节通常是个坏主意,因此我建议使用Lock同步对字典的访问。