October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk5 min

Workers Should Not Inherit Your Logging Handlers

Python logging handlers do not behave identically across multiprocessing start methods. Learn how to configure workers explicitly and send shared output through a queue and listener.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Whether a Python worker inherits logging handlers depends on how it starts. A child created with fork begins with a copy of the parent’s process state, while spawn starts a fresh interpreter and requires worker-side logging setup. For multiple workers writing to one destination, give that destination to one listener and send worker records through a queue.

What “inherit” means in Python logging

Python loggers pass records to handlers attached to the logger and, when propagation is enabled, to handlers on ancestor loggers. A worker can therefore emit to more than one handler if it has its own handler and also propagates to a parent logger with another handler.

As an Amazon Associate I earn from qualifying purchases.

With fork, the child starts from a copy of the parent’s process state. A logger and its configured handlers may consequently exist in the child. This is not a universal multiprocessing rule: with spawn, the child starts a fresh interpreter, so the worker must initialize its logging configuration. forkserver uses a different process-creation arrangement as well. When diagnosing unexpected output, identify the start method before assuming handler state was inherited.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose a logging architecture deliberately

Architecture Who owns the destination? Formatting and filtering Main trade-offs
Handlers in each worker Each worker opens or writes to its own handler; multiple ordinary file handlers do not provide standard cross-process serialization to one shared file. Workers format and filter locally. Can suit separate destinations, but sharing one file this way risks interleaved or conflicting writes. It also makes duplicate output possible if inherited and newly configured handlers both receive a record.
Queue plus listener One listener thread or process owns the file, rotating-file, console, or other output handlers. Workers enqueue records; the listener applies destination formatting, filters, and levels. QueueListener defaults to respect_handler_level=False; enable it when destination handler levels should filter queued records. Centralizes output, but requires queue lifecycle management, attention to queue capacity and serialization, and a clean shutdown sequence.
Socket receiver A receiver owns the destination handlers. Records are sent to the receiver for centralized handling. Another centralization design documented in the Logging Cookbook; it introduces receiver and socket setup rather than a multiprocessing queue.

For many workers writing to one shared file, the queue/listener design is the clearest standard-library pattern. Python’s Logging Cookbook explains that the standard logging package does not provide a standard way to serialize writes from multiple processes to one file.

Configure workers and a shared destination

Create the queue from the same multiprocessing context used to create the workers. Have workers send records to a QueueHandler, and let a listener own the real output handlers. The following is the core worker-side configuration; the application must create the queue, start the listener, and pass the queue into the worker using its chosen context.

import logging
from logging.handlers import QueueHandler

def configure_worker(log_queue):
    root = logging.getLogger()
    root.handlers.clear()
    root.addHandler(QueueHandler(log_queue))
    root.setLevel(logging.INFO)

Clearing the root handlers here is an intentional choice for a worker that should send records only to the queue. If the application needs worker-local output as well, configure it explicitly rather than leaving inherited handlers active by accident. Also inspect named loggers: a child logger with its own handler may propagate to the root and produce duplicate output.

  1. Create a compatible queue. Obtain a multiprocessing context and create its queue and processes from that context. Reusable libraries should accept a context from callers instead of imposing one; objects such as locks created by one context may not be compatible with processes using another.
  2. Set up the listener destination. Configure the listener’s file or other output handlers, including formatters, filters, and levels. If using QueueListener and destination handler levels must be honored, pass respect_handler_level=True.
  3. Initialize each worker. Attach a QueueHandler for the shared queue and set the intended logger levels and propagation behavior. Keep only handlers that belong in that worker’s design.
  4. Drain and stop cleanly. Stop and join workers, signal the listener to shut down, then stop and join the listener before application exit. QueueListener.stop() waits for its thread; failing to call it can leave queued records unprocessed. Python 3.14 added context-manager support for QueueListener.

Handle inherited handlers after fork

If a worker is created with fork, it may retain the parent’s logger configuration. Adding a queue handler without disabling or removing an inherited output handler can send the same record to both destinations. Inspect the root logger and relevant named loggers in the worker, then explicitly keep, remove, or disable handlers according to the intended design.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The Logging Cookbook’s multiprocessing example configures a parent-side setup logger and disables existing loggers in its worker and listener configurations so that logger does not remain active after fork. The example checks for POSIX because the setup logger does not exist in the same way on Windows, where fork is not used. This is an illustrative configuration, not a requirement to disable every existing logger in every application.

Rank #3
J. J. Keller 2024 OSHA Construction Safety Handbook, English
  • 2024 OSHA Construction Safety Book is the seventh edition with the new OSHA HazCom final rule on 5/20/24. While the rule takes effect 7/19/24, the compliance dates don’t begin until 1/19/26 per 29 CFR 1910.1200(j).
  • Construction Site Book offers quick access to essential OSHA regulations, jobsite hazards, and practical safety tips. It also helps employees identify hazards and prevent injuries and illnesses.
  • Features easy-to-read format, full-color images, chapter quizzes with answer key, and comes in a compact size making it a convenient reference for employees.
  • Critical topics include Confined Space Entry; Cranes & Derricks; Electrical Safety; Emergency Response; Ergonomics & Back Safety; Excavations; Fall Protection; First Aid & Bloodborne Pathogens; HazCom; Health & Wellness; Jobsite Exposures; Lockout/Tagout; Ladders & Stairways; Materials Handling/Storage; Motor Vehicles; PPE; Scaffolds; Site Safety & Security; Slips, Trips & Falls; Tool Safety; Welding, Cutting & Brazing; and Work Zone Safety.
  • Specifications: 5 1/4” x 7 1/4", English, Soft bound. 7th Edition. Copyright 2024.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Account for Python version and platform

Start-method defaults vary. The CPython multiprocessing documentation says macOS uses spawn by default, a change made in Python 3.8. In Python 3.14, the default on POSIX changed from fork to forkserver. Code that appeared to work by inheriting the parent’s handlers under an earlier or different start method may therefore behave differently elsewhere.

The multiprocessing documentation advises: “Libraries using multiprocessing or ProcessPoolExecutor should be designed to allow their users to provide their own multiprocessing context.” In practice, a library should avoid silently setting a global start method and should create context-sensitive objects, including queues, from the context the caller supplies.

Quick Recap

Bestseller No. 1
Bestseller No. 3
J. J. Keller 2024 OSHA Construction Safety Handbook, English
J. J. Keller 2024 OSHA Construction Safety Handbook, English
Specifications: 5 1/4” x 7 1/4", English, Soft bound. 7th Edition. Copyright 2024.
$15.44
Bestseller No. 4
Handbook on Well Logging
Handbook on Well Logging
Used Book in Good Condition
$59.17
Rank #4
Handbook on Well Logging
  • Used Book in Good Condition

Prevent queue recursion, loss, and formatting surprises

  • Do not send multiprocessing’s own queue DEBUG messages back to the same queue. multiprocessing.Queue can emit DEBUG messages through multiprocessing’s internal logger. If that logger uses a QueueHandler attached to that exact queue, the result can be deadlock or infinite recursion. Keep multiprocessing’s internal diagnostics away from the logging queue they describe.
  • Know what happens when a bounded queue fills. QueueHandler uses nonblocking put_nowait() by default. A full queue can cause handleError; when logging.raiseExceptions is false, records may be silently dropped. Choose queue capacity and failure handling with the application’s logging needs in mind.
  • Account for record preparation. QueueHandler.prepare() merges message arguments and exception information and removes unpickleable items so records can be transferred. This can constrain custom formatting downstream, especially exception formatting. Customize the handler if the listener needs information that preparation would otherwise remove.
  • Check logger propagation. A logger’s record can reach handlers on its ancestors while propagation is enabled. Decide whether named loggers should propagate to the root queue handler or use their own handlers; avoid configuring both paths unintentionally.

Official references

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.