@@ -26,8 +26,8 @@ To configure your environment for developing with the multicast library, follow
2626Key steps include:
2727
2828 1 . Ensuring you have a supported version of Python installed.
29- 2 . Use pip to install (e.g., ` pip install multicast ` )
30- 3 . Verify the installation works:
29+ 2 . Using pip to install (e.g., ` pip install multicast ` )
30+ 3 . Verifying the installation works:
3131
3232 | _ in ` Python ` _ | _ in ` bash ` _ |
3333 | ---------------| -------------|
@@ -145,8 +145,8 @@ handler = logging.StreamHandler() # example trivial log handler
145145multicast_logging_sink.addHandler(handler)
146146
147147# imports
148- from multiprocessing import Process as Process
149148import multicast
149+ from multiprocessing import Process
150150import random # for random port
151151
152152# Multicast group address and port
@@ -180,6 +180,7 @@ Low-level with example handler:
180180# imports
181181import multicast
182182import random # for random port
183+ import functools # for decorator func metadata
183184
184185# Multicast group address and port
185186MCAST_GRP = " 224.0.0.1" # Replace with your multicast group address (use IPv4 dotted notation)
@@ -195,7 +196,6 @@ MCAST_PORT = int(random.SystemRandom().randint(49152, 65535)) # Replace with yo
195196# Windows users must use option 1 or 2 for now.
196197# This address is per socket (e.g., can be chosen per socket even if on a single interface)
197198
198-
199199# Options for multicast listener
200200listener_options = {
201201 " is_daemon" : False , # bool: enable/disable daemon mode
@@ -207,7 +207,6 @@ listener_options = {
207207
208208# Example setup for Low-Level use-case
209209# Define a decorator to loop until able to print a string result of enough length
210- import functools
211210
212211
213212def printLoopStub (func ):
@@ -256,8 +255,8 @@ _and elsewhere (e.g., in another module or even on another system); an example f
256255
257256``` python3
258257# imports
259- from multiprocessing import Process as Process
260258import multicast
259+ from multiprocessing import Process
261260
262261# Multicast group address and port
263262MCAST_GRP = " 224.0.0.1" # Replace with your multicast group address (use IPv4 dotted notation)
@@ -295,7 +294,7 @@ finally:
295294 if p:
296295 p.join() # if not already handled don't forget to join the process and other overhead
297296 # hint: if you use a loop and need to know the exit code
298- didWork = (p is not None and int ( p.exitcode) <= int ( 0 ) ) # e.g. check for success
297+ didWork = (p is not None and p.exitcode <= 0 ) # e.g. check for success
299298
300299```
301300
@@ -306,6 +305,80 @@ finally:
306305
307306See also [ USAGE Guide] ( ./USAGE.md )
308307
308+ ### Why does multicast module logging require explicit handler setup instead of just basicConfig?
309+
310+ The multicast module uses a null log handler by default as part of its logging architecture. This
311+ means that simply calling ` logging.basicConfig(level=logging.INFO) ` is insufficient to display the
312+ ` multicast ` module's log records, as there's no active handler to capture and output them.
313+
314+ To see multicast module logging output, you must explicitly add a log handler:
315+
316+ ``` mermaid
317+
318+ sequenceDiagram
319+ participant Python as Your Python Code
320+ participant multicast as Multicast Module
321+ participant logging as `logging` module
322+
323+ Python-->>logging: import logging
324+ opt setup custom log handler
325+ create participant Handler as Your Explicit Log Handler
326+ Python-->>Handler: create `logger` object
327+ Python-->>logging: add custom log handler
328+ end
329+ Python-->>multicast: import multicast
330+ multicast-->>logging: add default logging.NullHandler log handler
331+ multicast-->>logging: logs any multicast module output
332+ opt has added custom log handler
333+ logging->>Handler: handle logging
334+ Handler->>logging: the handler logic
335+ end
336+ multicast-->>Python: initialized
337+ loop main stuff
338+ alt doing whatever
339+ Python-->>Python: Your Non-multicast logic
340+ else using multicast
341+ Python-->>multicast: make API call to multicast
342+ opt module has log output
343+ multicast-->>logging: logs any multicast module output
344+ opt has handler
345+ logging->>Handler: handle logging
346+ Handler->>logging: the handler logic
347+ end
348+ end
349+ multicast-->>Python: reply to API call
350+ end
351+ end
352+ Python-xPython: done
353+ opt has custom log handler
354+ destroy Handler
355+ Python--xHandler: cleanup
356+ end
357+ ```
358+
359+ #### Required approach - explicit handler setup
360+
361+ > [ !IMPORTANT]
362+ > ` logging ` must be setup _ before_ importing ` multicast ` or the ` NullHandler ` setup by ` multicast `
363+ > will be first and still be-able to intercept the module's ` logging.LogRecords ` just as it
364+ > normally would.
365+
366+ ```
367+ import logging
368+ multicast_logging_sink = logging.getLogger()
369+ multicast_logging_sink.setLevel(logging.INFO) # optional, otherwise the module is very quiet
370+ handler = logging.StreamHandler() # replace with your explicit handler
371+ multicast_logging_sink.addHandler(handler)
372+ ```
373+
374+ This explicit setup ensures that:
375+
376+ * The log level is set appropriately (e.g., ` logging.INFO ` )
377+ * An active handler (e.g., ` StreamHandler ` ) is added to capture module log records
378+ * The multicast module's log output becomes visible to users
379+ * While logging.basicConfig() might seem simpler, it won't work with the multicast module's logging
380+ architecture and will result in no visible log output from the library.
381+
309382### How do I run and interpret the test suite for this project?
310383
311384To run the test suite, follow the instructions in the [ Testing Guide] ( ./Testing.md ) .
0 commit comments