2016-11-11 23 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