Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow 'total' to be updated during runtime #82

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ In general lines, just retrieve the items, enter the `alive_bar` context manager
- the first argument of the `alive_bar` is the expected total, so it can be anything that returns an integer, like `qs.count()` for querysets, `len(items)` for iterables that support it, or even a static integer;
- the `bar()` call is what makes the bar go forward -- you usually call it in every iteration after consuming an item, but you can get creative! Remember the bar is counting for you _independently of the iteration process_, only when you call `bar()` (something no other progress bar have), so you can use it to count anything you want! For example, you could call `bar()` only when you find something expected and then know how many of those there were, including the percentage that it represents! Or call it more than once in the same iteration, no problem at all, you choose what you are monitoring! The ETA will not be that useful unfortunately;
- to retrieve the current `bar()` count/percentage, you can call `bar.current()`.
- to update `total` during runtime, use the `bar.update_total(nn)` function.

So, you could even use it without any loops, like for example:

Expand Down Expand Up @@ -375,6 +376,27 @@ And if you want to do even more, exciting stuff lies ahead!
> ---
</details>

<details>
<summary><strong><em>You need to update total in runtime?</em></strong></summary>

> ### Dynamic total
>
> Imagine a multi-threaded application where one thread collects items in the
> file system, on which a second thread does work.
>
> In this case, the `total` is still growing while work is already done on the
> available data.
>
> You can use `bar.update_total(new_total)` to cope with that.
> ```
> with alive_bar(1) as bar:
> bar.update_total(check_current_total())
> bar()
> ```
>
> ---
</details>


## Interesting facts

Expand Down
25 changes: 16 additions & 9 deletions alive_progress/core/progress.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,16 +205,23 @@ def pause_monitoring():
thread.start()

if total or not config.manual: # we can count items.
logic_total, rate_spec, factor, current = total, 'f', 1.e6, lambda: run.count # noqa
run.total, run.logic_total, rate_spec, factor, current = total, total, 'f', 1.e6, lambda: run.count # noqa
else: # there's only a manual percentage.
logic_total, rate_spec, factor, current = 1., '%', 1., lambda: run.percent # noqa
run.logic_total, rate_spec, factor, current = 1., '%', 1., lambda: run.percent # noqa

def update_total(n):
run.total = n
run.logic_total = n
run.gen_eta = gen_simple_exponential_smoothing_eta(.5, run.logic_total)
run.gen_eta.send(None)

bar_handle.text, bar_handle.current, bar_handle.update_total = set_text, current, update_total

bar_handle.text, bar_handle.current = set_text, current
if total or config.manual: # we can track progress and therefore eta.
spec = '({{:.1{}}}/s, eta: {{}})'.format(rate_spec)
gen_eta = gen_simple_exponential_smoothing_eta(.5, logic_total)
gen_eta.send(None)
stats = lambda: spec.format(run.rate, to_eta_text(gen_eta.send((current(), run.rate))))
run.gen_eta = gen_simple_exponential_smoothing_eta(.5, run.logic_total)
run.gen_eta.send(None)
stats = lambda: spec.format(run.rate, to_eta_text(run.gen_eta.send((current(), run.rate))))
bar_repr = config.bar(config.length)
else: # unknown progress.
bar_repr = config.unknown(config.length, config.bar)
Expand Down Expand Up @@ -248,13 +255,13 @@ def fps():
if total:
if config.manual:
def update_hook():
run.count = int(math.ceil(run.percent * total))
run.count = int(math.ceil(run.percent * run.total))
else:
def update_hook():
run.percent = run.count / total
run.percent = run.count / run.total

monitor = lambda: '{}{}/{} [{:.0%}]'.format( # noqa
'(!) ' if end and run.count != total else '', run.count, total, run.percent
'(!) ' if end and run.count != run.total else '', run.count, run.total, run.percent
)
elif config.manual:
update_hook = lambda: None # noqa
Expand Down