2016-11-11 151 views
0

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

不能访问外部局部变量,需要使用'global'或'class'来访问任何地方。但是如果从外部访问变量,则会失去同步。最好的结果是存储结果比存储数据更好! – dsgdfg

回答

1

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

问题的近因是你试图用错误的键引用字典。当您将该ID存储在字典中时,首先将其转换为int,但是当您从主线程访问该ID时,您正在使用用户提供的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