0

I have a thread (new_client_thread) that updates a dictionary and print it. When I am trying to print the dictionary again but from the main thread, the dictionary was not changed. When the thread (new_client_thread) changes the dictionary again all changes were saved too, but only inside this thread and not in the main.

This is my 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()

This is my socket control

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)
Rony Cohen
  • 87
  • 2
  • 14
  • Can't access local variables outside, need using `global` or `class` for access anywhere. But you lose synchronism if access variable from outside. Best thing `storing result better than storing data !` – dsgdfg Nov 11 '16 at 12:42

1 Answers1

1

In CPython, you should have no trouble updating a dict in one thread, and accessing it in another (see Using a global dictionary with threads in Python).

The proximate cause of your problem is that you are attempting to reference the dictionary with the wrong key. When you store the ID in the dictionary, you're first converting it to an int but when you access it from the main thread, you're using the str input provided by the user; i.e. int('88') is not the same key as '88'.

If you change the line:

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

to:

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

You'll progress to the next error (which is that the socket object doesn't have a send_message method but if you change that to .send, it will work).

To return to the initial subject, it's generally a bad idea to leave your code relying on an implementation detail such as CPython's Global Interpreter Lock, so I'd suggest synchronizing access to your dictionary with Lock.

Community
  • 1
  • 1
Gil Hamilton
  • 11,973
  • 28
  • 51