Repository navigation
ENH: adoption of the built-in python loggers instead of simple prints #450
Description
Activity
- addedEnhancementNew feature or request, including adjustments in current codesNew feature or request, including adjustments in current codes
on Oct 30, 2023 - changed the title
[-]ENH: use of built-in python loggers instead of prints[/-][+]ENH: adoption of the built-in python loggers instead of simple prints[/+]on Oct 30, 2023 Hey @Gui-FernandesBR, I did some research on how other libraries handle this same situation. Here's what I found:
pandas: The
.info()method writes to abufparameter that defaults tosys.stdout. Noprint(), nologging. The user can redirect by passing any writable buffer (e.g.StringIO).matplotlib: Uses pure
loggingthroughout with aset_loglevel()helper for the user. Silent by default, user configures output. This would be a breaking change for RocketPy since.info()calls would produce no output without user configuration.scipy: Uses
print()directly when the user explicitly requests output viadisp=Trueorverbose=True. Useswarnings.warn()for internal events. Simple and backwards compatible, but no logging benefits.astropy: Built a custom
AstropyLoggersubclass that adds aStreamHandlerinternally so output appears in the terminal by default. Works well, but violates the official Python recommendation ("do not add any handlers other than NullHandler to your library's loggers").statsmodels:
.summary()returns an object that implements__str__. The user explicitly callsprint(result.summary()). Clean, but changes the API and would be a breaking change.
I also checked the Python logging guide, which makes this distinction:
"Display console output for ordinary usage of a command line script or program: print()"
"Report events that occur during normal operation: logger.info()"
I asked Claude to help me analyse the pros and cons of each approach:
Option A: pandas approach (
bufparameter)- ✅ Backwards compatible
- ✅ No code duplication
- ✅ Output is redirectable
- ❌ No logging integration for
.info()calls - ❌ Requires refactoring all
.info()methods to accept abufargument
Option B: pure logging (matplotlib style)
- ✅ Full logging integration
- ✅ No code duplication
- ✅ No
print()anywhere - ❌ Breaking change —
.info()becomes silent without user configuration - ❌ Requires users to know how to configure logging
Option C: split responsibilities Keep
print()only inprints/(explicitly user-requested output) and uselogger.*only in execution files (internal runtime events).- ✅ Backwards compatible — getting started notebook works unchanged
- ✅ No code duplication — each message type has its own place
- ✅ Users benefit from logging for simulation events
- ❌ Two different mechanisms in the same codebase
Option D: astropy approach (custom logger with built-in StreamHandler)
- ✅ Backwards compatible
- ✅ Full logging integration
- ✅ No
print()anywhere - ❌ Violates official Python recommendation for libraries
- ❌ More complex to implement and maintain
What do you think? Which approach do you think would be the best fit for the project? Once you give your feedback I will update the implementation and fix the PR accordingly.
- linked a pull request that will close this issueENH: Add python loggers #973
on Jun 20, 2026 Hey @YuriCastroDev, thanks for the deep dive into how other libraries handle this!
Let's move forward with a refined version of Option C, combined with a user-friendly helper function. This addresses the code duplication concern while ensuring full backward compatibility.
Here is the architecture I believe we should aim for:
- Strict Separation of Responsibilities:
- Keep
print()for User Reports: Methods explicitly called by the user to display data (likeflight.info(),.all_info(), and files inprints/) should continue usingprint(). When a user calls these, they are explicitly expecting terminal output. - Use
loggingfor Execution Tracking: Internal events like simulation progress, missing motors, geometry auto-corrections, and solver ticks should uselogger.debug(),logger.info(), orlogger.warning(). - This won't cause code duplication because a message is either a final report (print) OR a background runtime event (log). They serve entirely different purposes.
- Keep the
NullHandler:
- Maintain the
logging.NullHandler()in__init__.py. Internal logs should remain silent by default, adhering to Python's official guidelines for libraries.
- Add a UX Helper Function (The Matplotlib approach):
- To prevent users from having to write
loggingboilerplate just to see what's happening under the hood, let's create a utility function likerocketpy.utils.enable_logging(level="INFO"). This function will simply attach aStreamHandlerto the RocketPy loggers. I imagine something like:
import rocketpy rocketpy.utils.enable_logging(level="INFO")
This approach guarantees that our Getting Started notebooks will work perfectly out of the box with zero breaking changes, strictly follows Python best practices, and provides power users with the robust logging capabilities they asked for.
Let me know if this makes sense, and feel free to update the PR! Btw if you prefer, you could break down this issue onto different PRs.
Reacted by Yuri de Castro
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsBacklog
Is your feature request related to a problem? Please describe.
RocketPy doesn't offer a good way of tracking the execution steps when running a flight simulation.
There are some prints around the code, but they do not cover all the classes and do not look robust enough for a definitive solution as rocketpy wants to be.
Describe the solution you'd like
Additional context