Well, my friend, you’re in luck because I’m here to help!
To set the stage, let’s create a simple example of what we want to achieve. We have a main process that starts other processes and each of those processes will log something. Let’s say our main process looks like this:
# Import the necessary modules
import logging # Import the logging module to enable logging functionality
from multiprocessing import Process # Import the Process class from the multiprocessing module to enable multiprocessing functionality
# Define the MainProcess class, which inherits from the Process class
class MainProcess(Process):
# Define the constructor method for the MainProcess class
def __init__(self):
super().__init__() # Call the constructor method of the Process class
self.logger = logging.getLogger(__name__) # Create a logger object for the MainProcess class using the __name__ attribute
# Define the run method for the MainProcess class
def run(self):
# Perform some actions here
pass
# Check if the script is being run directly
if __name__ == "__main__":
p = MainProcess() # Create an instance of the MainProcess class
p.start() # Start the process by calling the start method
And let’s say our other processes look like this:
# Import the necessary modules
import logging # Import the logging module to enable logging functionality
from multiprocessing import Process # Import the Process class from the multiprocessing module to enable multiprocessing functionality
# Create a class for our other process
class OtherProcess(Process):
def __init__(self):
super().__init__() # Call the __init__ method of the parent class to initialize the process
self.logger = logging.getLogger(__name__) # Create a logger object for this process using the __name__ attribute
def run(self):
# Perform some important task and log it
self.logger.info("I'm doing something important in another process") # Use the logger object to log a message indicating the task being performed
# Check if the script is being run directly
if __name__ == "__main__":
p = OtherProcess() # Create an instance of the OtherProcess class
p.start() # Start the process by calling the start() method
Now, if we run this code as is, our logs will be mixed up because each process has its own logger and they all have the same name (the name of the module). To fix that, let’s add a unique identifier to each logger so that we can easily distinguish them. Here’s how:
# Import the necessary libraries
import logging
from multiprocessing import Process
# Create a class for the main process
class MainProcess(Process):
# Initialize the class
def __init__(self):
# Call the parent class constructor
super().__init__()
# Create a logger for this process with the name of the module
self.logger = logging.getLogger(__name__)
# Set the log level for this logger to INFO
self.logger.setLevel(logging.INFO)
# Create a formatter for the log messages
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
# Create a file handler for the log messages
handler = logging.FileHandler("logs/main_process.log")
# Set the log level for this handler to INFO
handler.setLevel(logging.INFO)
# Set the formatter for this handler
handler.setFormatter(formatter)
# Add the handler to the logger
self.logger.addHandler(handler)
# Define the run method for the process
def run(self):
# Do something here
pass
# Check if the script is being run directly
if __name__ == "__main__":
# Create an instance of the MainProcess class
p = MainProcess()
# Start the process
p.start()
And let’s modify our other processes to use the same logger as before but with a unique identifier:
# Import the necessary libraries
import logging # Import the logging library to create and manage logs
from multiprocessing import Process # Import the Process class from the multiprocessing library
# Create a class for the other process, inheriting from the Process class
class OtherProcess(Process):
# Initialize the class
def __init__(self):
super().__init__() # Call the __init__ method of the parent class
self.logger = logging.getLogger(__name__) # Create a logger with the name of the current module
self.logger.setLevel(logging.INFO) # Set the log level for this logger to INFO
formatter = logging.Formatter('%(asctime)s %(levelname)s [%(processName)s] %(message)s') # Create a formatter for the log messages
handler = logging.FileHandler("logs/other_processes.log") # Create a file handler to write the logs to a file
handler.setLevel(logging.INFO) # Set the log level for this handler to INFO
handler.setFormatter(formatter) # Set the formatter for this handler
self.logger.addHandler(handler) # Add the handler to the logger
# Define the run method for the process
def run(self):
# Do something here and log it!
self.logger.info("I'm doing something important in another process") # Log a message using the logger
# Check if the current module is being run as the main program
if __name__ == "__main__":
p = OtherProcess() # Create an instance of the OtherProcess class
p.start() # Start the process
In this example, we added a unique identifier to the logger by setting the `processName` attribute of our handler. This will automatically add the name of the current process when logging messages.
And that’s it! Now you can easily distinguish logs from different processes in your log files without having them mixed up.