PowerBroker2 / pySerialTransfer

Python package to transfer data in a fast, reliable, and packetized form
MIT License
143 stars 35 forks source link

Replace print statements with logging in Python library #103

Closed robberwick closed 4 months ago

robberwick commented 4 months ago

This PR replaces all instances of print statements in the library with Python's built-in logging module. The print function, while useful for simple debugging or output, has several disadvantages when used in a library:

  1. Lack of flexibility: print always writes to standard output, and cannot be easily redirected to other destinations like a file or a network socket.
  2. No severity levels: print does not distinguish between different kinds of messages, such as debug, info, warning, and error messages.
  3. No control for library users: If a library uses print, the application using the library cannot easily control when these messages should be output.

On the other hand, the logging module provides a flexible framework for emitting log messages from Python programs. It is based on a modular and configurable architecture, using handlers, formatters, and filters to generate log messages of different severity levels to various output destinations.

By using logging instead of print, we can provide users of the library with the following benefits:

  1. Control over message level: Users can choose to only display messages above a certain severity level.
  2. Control over message destination: Users can choose to route messages to one or more destinations, including the console, a file, a network socket, or even an email server.
  3. Control over message format: Users can choose the precise format of their log messages.

Users of the library can configure logging in their application as follows:

import logging

# Create a custom logger
logger = logging.getLogger(__name__)

# Create handlers
c_handler = logging.StreamHandler()
f_handler = logging.FileHandler('file.log')
c_handler.setLevel(logging.WARNING)
f_handler.setLevel(logging.ERROR)

# Create formatters and add it to handlers
c_format = logging.Formatter('%(name)s - %(levelname)s - %(message)s')
f_format = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
c_handler.setFormatter(c_format)
f_handler.setFormatter(f_format)

# Add handlers to the logger
logger.addHandler(c_handler)
logger.addHandler(f_handler)

In this example, two handlers are created: c_handler which logs warning messages or higher to the console, and f_handler which logs error messages or higher to a file. They are added to the logger, which replaces the NullHandler added by the library. Now, when the library code calls logging.getLogger(__name__), it will return the logger configured in the application, and log messages will be handled according to the application's configuration.