Python Socket programming chat - getting a handle on PEP conventions
Instead of always manually parsing sys.argv, you can use the standard library tool argparse. It automatically enforces the right usage and prints a nicely formatted usage if not. For your given example it would look like this:

import argparse

def ip_address(ip):
    # TODO: implement checking if IP is valid
    return ip

def parse_args(args=None):
    parser = argparse.ArgumentParser(description="Tool for server client connection.",
                                     epilog="Ensure the socket server is live before using this tool.")
    parser.add_argument("ip", type=ip_address, help="The IP address of the server")
    parser.add_argument("port", type=int, help="The port where the server listens.")
    return parser.parse_args(args)


I put it into a function so you can test it without having to run the whole code, by passing a list of strings to the function. It also allows setting the type of arguments, which can be any callable (so in the above example you need to have e.g a function called ip_address that can check if the argument is a valid IP address). The help messages generated by this example are like this:

$ python3 /tmp/sock_client.py 127.0.0.1
usage: sock_client.py [-h] ip port
sock_client.py: error: the following arguments are required: port

$ python3 /tmp/sock_client.py -h       
usage: sock_client.py [-h] ip port

Tool for server client connection.

positional arguments:
  ip          The IP address of the server
  port        The port where the server listens.

optional arguments:
  -h, --help  show this help message and exit

Ensure the socket server is live before using this tool.


You can also add optional arguments, arguments with multiple parameters, mutually exclusive arguments/argument groups. Check out the documentation for more examples.



Instead of iterating only over the keys of a dictionary, iterate over the keys and values at the same time if you need both of them. Also, don't use too short names. No matter how nice your docstring is, it is always better if your function signature already tells you everything you need to know.

def send_user(message, user):
    """
    Sends a message to a single client.

    Parameter:
    message -- the message to send
    user    -- the client to send to
    """
    for client, user_name in CLIENT_LIST.items():
        # only specific client/user
        if user_name == user:
            client.send(bytes(message, "utf8"))


Also, don't lie in your docstrings. This function sends a message to every client with the right name (i.e. value in the dictionary)! You can just break after you have found the user to ensure there is only one, or adapt the docstring to the reality of the code. In either case, add tests to ensure that your code does what it should.

Calling what appears to be a dictionary CLIENT_LIST is one of the reasons why you should not include the type in the variable. Here it is very misleading and probably wrong! Just call them CLIENTS or ALL_CLIENTS or even USER_NAMES.



There are two widely used docstring conventions (that I know of, i.e. in scientific computing). The first is the Google style and the other one the numpy style. Your code seems to be closer to the latter, but as long as you are consistent and include all necessary information you should be fine.