<@ULVA73B9P> how do I make the tqdm progress bar t...
# ask-marvin
m
@Marvin how do I make the tqdm progress bar to be logged to prefect task logs
m
thought for 125.1 seconds
Short version: don’t try to log the live tqdm bar itself.
tqdm
is designed for interactive terminals and uses carriage returns / terminal control characters. Prefect task logs are line-oriented, so the animated bar usually won’t render correctly in task logs. What works best in Prefect 3.x - use
get_run_logger().info(...)
for periodic progress updates, or - use
print(...)
with
log_prints=True
Example:
Copy code
python
from prefect import flow, task
from prefect.logging import get_run_logger
from tqdm import tqdm
import time

@task
def work():
    logger = get_run_logger()
    items = range(100)

    for i, item in enumerate(tqdm(items, disable=True), start=1):
        time.sleep(0.05)

        if i % 10 == 0:
            <http://logger.info|logger.info>(f"Progress: {i}/{len(items)} complete")

@flow
def my_flow():
    work()

if __name__ == "__main__":
    my_flow()
If you want
print()
statements to appear in logs:
Copy code
python
from prefect import flow, task
import time

@task(log_prints=True)
def work():
    for i in range(100):
        time.sleep(0.05)
        if (i + 1) % 10 == 0:
            print(f"Progress: {i + 1}/100 complete")

@flow
def my_flow():
    work()
A practical pattern if you still want tqdm locally: - enable tqdm only when running interactively - disable it in Prefect runs, and log checkpoints instead
Copy code
python
import sys
from tqdm import tqdm

use_tqdm = sys.stdout.isatty()

for i in tqdm(range(100), disable=not use_tqdm):
    ...
Why this happens - Prefect does not turn arbitrary streaming terminal output into a proper progress bar in logs -
log_prints=True
captures
print()
output, not the dynamic terminal behavior that tqdm relies on Recommended approach - for Prefect UI/task logs: use
<http://logger.info|logger.info>(...)
- for local scripts: use
tqdm
- if you need both: disable tqdm in Prefect and emit periodic log lines Relevant docs: - Prefect logging docs - Prefect flows - Prefect tasks If you want, I can show you a small helper that wraps
tqdm
and automatically logs every
N
steps in a Prefect-friendly way.
m
@Marvin can basic logging python module make each log can be tracked in each task or should I use prefect native logs
m
thought for 13.2 seconds
Use Prefect native logging if you want logs to be reliably associated with the specific flow run / task run in the Prefect UI. Recommendation - Inside flows/tasks: use
from prefect.logging import get_run_logger
- Use standard
logging
only if you specifically configure it and understand it may not automatically attach Prefect run context the way native logs do Example:
Copy code
python
from prefect import flow, task
from prefect.logging import get_run_logger

@task
def my_task():
    logger = get_run_logger()
    <http://logger.info|logger.info>("This log is tied to this task run")

@flow
def my_flow():
    logger = get_run_logger()
    <http://logger.info|logger.info>("This log is tied to this flow run")
    my_task()
With Python’s basic logging module:
Copy code
python
import logging

logger = logging.getLogger(__name__)
<http://logger.info|logger.info>("hello")
that log may go to stdout or your configured handlers, but it is not the best choice if your goal is: - seeing it in Prefect task logs - having it clearly attributed to the correct task run - preserving Prefect metadata like run IDs Rule of thumb - Need logs in Prefect UI per task? → use
get_run_logger()
- Need app/library logging outside Prefect too? → you can still use
logging
, but often it’s best to bridge it into Prefect or log through Prefect within task/flow code Also: -
print()
can be captured with
log_prints=True
- but structured task logging is better with
get_run_logger()
Docs: - Prefect logging - Prefect loggers API If you want, I can show: 1. how to forward standard Python logging into Prefect logs, or 2. a best-practice logging setup for tasks + libraries.
m
can I make the logger to be instantiated inside the python script that is used in certain task and prefect still succesfully map each log to respecitve task @Marvin
m
thought for 11.8 seconds
Yes — if that script is executed within the task run context, Prefect can still associate logs with the correct task as long as you use Prefect’s logger. Best practice: instantiate the logger inside the function that runs during the task, using
get_run_logger()
.
Copy code
python
from prefect import task, flow
from prefect.logging import get_run_logger

def helper_script_logic():
    logger = get_run_logger()
    <http://logger.info|logger.info>("This will be attached to the current task run")

@task
def my_task():
    helper_script_logic()

@flow
def my_flow():
    my_task()

if __name__ == "__main__":
    my_flow()
That works because
get_run_logger()
pulls the current run context at execution time. Important caveat If you instantiate a logger at import time or outside a running flow/task context, Prefect may not have task context available. Example of what to avoid:
Copy code
python
from prefect.logging import get_run_logger

logger = get_run_logger()  # bad if module imported before task is running

def helper():
    <http://logger.info|logger.info>("May fail or not map correctly")
Instead, do this:
Copy code
python
from prefect.logging import get_run_logger

def helper():
    logger = get_run_logger()
    <http://logger.info|logger.info>("Mapped to the current task")
Using standard Python logging inside helper scripts If your helper script does this:
Copy code
python
import logging
logger = logging.getLogger(__name__)
then those logs are not guaranteed to be mapped to the Prefect task in the UI the same way. They may show up in worker/stdout logs depending on configuration, but not as clean task-run logs. So the answer is: - Yes — if the logger is created inside code called by the task, and you use
get_run_logger()
- No guarantee — if you use plain
logging.getLogger(...)
and expect Prefect task attribution automatically A good pattern for reusable scripts is to accept an optional logger:
Copy code
python
from prefect import task, flow
from prefect.logging import get_run_logger

def do_work(logger=None):
    logger = logger or get_run_logger()
    <http://logger.info|logger.info>("Doing work")

@task
def my_task():
    logger = get_run_logger()
    do_work(logger=logger)

@flow
def my_flow():
    my_task()
That makes the script reusable both: - inside Prefect - outside Prefect, where you can pass a normal Python logger Docs: - Prefect logging - get_run_logger If you want, I can give you a pattern for a separate module/script file that works both in Prefect tasks and as a standalone Python script.