Mehdi Lallouache
02/18/2026, 8:19 AMMarvin
02/18/2026, 8:19 AMMarvin
02/18/2026, 8:23 AMlog_prints=True (easy typo).
Short answer: Prefect only captures print() when it’s executed inside an active flow/task run and only to stdout/stderr. If prints happen outside that context or in processes Prefect doesn’t control, they won’t show up. Here are the most common causes and how to fix them.
Why prints may not show up even with log_prints=True
- Printed outside a run context
- Before/after the flow or task actually runs (e.g., module import time, top-level code, or after returning from a task).
- Fix: Move prints inside the `@flow`/`@task` function bodies.
- Prints happen in another process that Prefect didn’t start
- Examples: subprocess.run(...), multiprocessing you spawn yourself, or libraries that launch workers (Dask, Ray, Spark, shell commands).
- Fix: Capture and log the output yourself:
from prefect import flow, get_run_logger
import subprocess
@flow(log_prints=True)
def my_flow():
r = subprocess.run(["python", "-c", "print('hello')"], capture_output=True, text=True)
logger = get_run_logger()
if r.stdout:
<http://logger.info|logger.info>(r.stdout.strip())
if r.stderr:
logger.warning(r.stderr.strip())
- Logging level filters out INFO
- print() is logged at INFO. If your logging level/handler is WARNING or higher, the messages won’t appear.
- Fix: ensure INFO level is enabled (e.g., set PREFECT_LOGGING_LEVEL=INFO).
- Printing to a custom file handle
- Only default print(...) (stdout) and print(..., file=sys.stderr) are captured. Anything like print(..., file=open('x.txt','w')) is not.
- Fix: don’t override file unless it’s `sys.stdout`/`sys.stderr`.
- log_prints not actually enabled in that scope
- Resolution order is: explicit on the flow/task → inherit from parent flow context → PREFECT_LOGGING_LOG_PRINTS env var (default False).
- A subflow or task can override the parent. If something is log_prints=False in the chain, prints in that scope won’t be captured.
What does work
- Any print() inside a flow or task run (in the same Python process) with log_prints=True will be captured and logged at INFO.
- Tasks executed by Prefect (regardless of runner) will patch print() during the task’s run. If you spawn your own subprocesses inside that task, those subprocess prints won’t be captured unless you capture and log them manually (as above).
Recommended ways to make it consistent
- Turn it on at the flow level so tasks inherit it:
from prefect import flow, task
@task
def do_thing():
print("This will be logged")
@flow(log_prints=True)
def main():
print("This will be logged")
do_thing()
- Or set it globally:
# shell
export PREFECT_LOGGING_LOG_PRINTS=true
- If you rely on external commands/processes, always capture their output and send it to the run logger (see subprocess example above).
Quick check-list
- Are the missing prints inside the actual `@flow`/`@task` body?
- Do you spawn subprocesses/multiprocessing inside your code?
- Is PREFECT_LOGGING_LEVEL at least INFO?
- Are you printing to stdout/stderr (not a custom file)?
- Any subflow/task explicitly set log_prints=False?
If you can share:
- A minimal code snippet where prints go missing
- Your task runner and whether you spawn subprocesses/multiprocessing
- How you enabled log_prints (decorator vs env var)
…I can pinpoint the exact cause and suggest the best fix.