Skip to content

Commit 5639e7c

Browse files
[DOCUMENTATION] Further improved the FAQ documentation (- WIP PR #429 -)
Changes in file docs/FAQ.md: * simplified code examples some more * added answer about use of logging handlers * style fixes Changes in file docs/USAGE.md: * style fixes
1 parent 2b5841f commit 5639e7c

File tree

2 files changed

+82
-8
lines changed

2 files changed

+82
-8
lines changed

docs/FAQ.md

Lines changed: 80 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ To configure your environment for developing with the multicast library, follow
2626
Key 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
145145
multicast_logging_sink.addHandler(handler)
146146

147147
# imports
148-
from multiprocessing import Process as Process
149148
import multicast
149+
from multiprocessing import Process
150150
import random # for random port
151151

152152
# Multicast group address and port
@@ -180,6 +180,7 @@ Low-level with example handler:
180180
# imports
181181
import multicast
182182
import random # for random port
183+
import functools # for decorator func metadata
183184

184185
# Multicast group address and port
185186
MCAST_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
200200
listener_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

213212
def 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
260258
import multicast
259+
from multiprocessing import Process
261260

262261
# Multicast group address and port
263262
MCAST_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
307306
See 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

311384
To run the test suite, follow the instructions in the [Testing Guide](./Testing.md).

docs/USAGE.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,10 @@ finally:
134134
> directly with something like this:
135135
>
136136
> ```python3
137+
> from multicast.hear import McastServer, HearUDPHandler
137138
> with McastServer((MCAST_GRP, MCAST_PORT), HearUDPHandler) as server:
138139
> server_initialized = True
139-
> server.serve_forever()
140+
> server.serve_forever() # ... use CTL+C (or signal 2) to shutdown the server
140141
> ```
141142
>
142143
> This is essentially what the

0 commit comments

Comments
 (0)