Skip to content

ENH: adoption of the built-in python loggers instead of simple prints #450

Description

@Gui-FernandesBR

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

  • Adopt the best practices from the built-in logging facility of Python. A basic guide is available here: https://docs.python.org/3/howto/logging.html#logging-basic-tutorial. Further investigation may be needed to understand how exactly this module works.
  • Ensure that at least the core classes are supports log messages from logging.
  • We should also allow for a log file generation to be accessed by the end of the execution.
  • The Flight class could be the first one to receive this new feature.

Additional context

  • I'm guessing this implementation would leverage the debugging process of rocketpy's simulations, saving valuable time for both devs and users.
  • It is not a good idea to define log handlers inside the library, but it is totally OK to use loggers instead of prints so the final user can decide how to format or handle the loggers data.

Activity

  1. added
    EnhancementNew feature or request, including adjustments in current codes
    on Oct 30, 2023
  2. 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
  3. self-assigned this
    on Feb 24, 2024
  4. YuriCastroDev commented on Jun 20, 2026

    @YuriCastroDev
    Contributor

    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 a buf parameter that defaults to sys.stdout. No print(), no logging. The user can redirect by passing any writable buffer (e.g. StringIO).

    matplotlib: Uses pure logging throughout with a set_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 via disp=True or verbose=True. Uses warnings.warn() for internal events. Simple and backwards compatible, but no logging benefits.

    astropy: Built a custom AstropyLogger subclass that adds a StreamHandler internally 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 calls print(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 (buf parameter)

    • ✅ Backwards compatible
    • ✅ No code duplication
    • ✅ Output is redirectable
    • ❌ No logging integration for .info() calls
    • ❌ Requires refactoring all .info() methods to accept a buf argument

    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 in prints/ (explicitly user-requested output) and use logger.* 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.

  5. linked a pull request that will close this issueENH: Add python loggers #973on Jun 20, 2026
  6. Gui-FernandesBR commented on Jun 20, 2026

    @Gui-FernandesBR
    MemberAuthor

    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:

    1. Strict Separation of Responsibilities:
    • Keep print() for User Reports: Methods explicitly called by the user to display data (like flight.info(), .all_info(), and files in prints/) should continue using print(). When a user calls these, they are explicitly expecting terminal output.
    • Use logging for Execution Tracking: Internal events like simulation progress, missing motors, geometry auto-corrections, and solver ticks should use logger.debug(), logger.info(), or logger.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.
    1. 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.
    1. Add a UX Helper Function (The Matplotlib approach):
    • To prevent users from having to write logging boilerplate just to see what's happening under the hood, let's create a utility function like rocketpy.utils.enable_logging(level="INFO"). This function will simply attach a StreamHandler to 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

EnhancementNew feature or request, including adjustments in current codes

Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions