【问题标题】:Dictionary update inside function but not outside it字典更新函数内部但不在函数外部
【发布时间】:2016-11-11 11:33:25
【问题描述】:

我有一个线程 (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)

【问题讨论】:

  • 无法访问外部的局部变量,需要使用globalclass在任何地方访问。但是,如果从外部访问变量,则会失去同步。最好的东西storing result better than storing data !

标签: python multithreading sockets


【解决方案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 同步。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多