pythonfunctionsocketsobjectmethods

Passing a socket to a function and modifying it, or creating a socket inside the function and returning it


I am creating a simple python ASGI server and I have doubts about my implementation of the function that creates the server's socket.

Should I create the server's socket inside the function and return it like this:

class Server:
    def __init__(self, host: Optional[str] = None,
                 port: Optional[int] = None,
                 debug_mode: bool = False) -> None:
        self.host = host if host is not None else socket.gethostbyname('localhost')
        self.port = port if port is not None else 8000
        self.server_sock = self.initialize_server()
        self.debug_mode = debug_mode

    def initialize_server(self) -> Optional[socket.socket]:
        try:
            server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            server_sock.setblocking(False)
            server_sock.bind((self.host, self.port))
            return server_sock
        except socket.error as e:
            return None

Or should I pass an empty socket object to the function, modify it, like so:

class Server:
    def __init__(self, host: Optional[str] = None,
                 port: Optional[int] = None,
                 debug_mode: bool = False) -> None:
        self.host = host if host is not None else socket.gethostbyname('localhost')
        self.port = port if port is not None else 8000
        self.server_sock = None
        self.initialize_server()
        self.debug_mode = debug_mode

    def initialize_server(self) -> Optional[socket.socket]:
        try:
            self.server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            self.server_sock.setblocking(False)
            self.server_sock.bind((self.host, self.port))
        except socket.error as e:
            self.server_sock = None

I would like to know if one implementation is preferable over the other, why, and if it can be implemented even better somehow.


Solution

  • IMO you will probably use the socket later after using your initialize_server method. So you should keep your second snippet to avoid constantly passing the server AND the socket to each function targetting this connection.

    After typing correction, my favorite option is:

    class Server:
        def __init__(self, host: Optional[str] = None,
                     port: int = 8000,
                     debug_mode: bool = False) -> None:
            self.host = host if host is not None else socket.gethostbyname('localhost')
            self.port: int = port
            self.server_sock: Optional[socket.socket] = None
            self.initialize_server()
            self.debug_mode = debug_mode
    
        def initialize_server(self) -> None:
            try:
                self.server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                self.server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
                self.server_sock.setblocking(False)
                self.server_sock.bind((self.host, self.port))
            except socket.error as e:
                self.server_sock = None
    

    One more advice, start to log everything when you handle your socket (example: at the exception you should log the error with logging module)