-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Reposition bars below a closed bar #1502
base: master
Are you sure you want to change the base?
Conversation
tqdm/std.py
Outdated
finally: | ||
# Remove from internal set | ||
self._decr_instances(self) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved this to a finally block to first adjust the closed bar to the top row, before other bars adjust their position upwards. This results in a cleaner screen update, I think.
The reproducer demo from #1496 looks like this when using the changes in this PR: Screen.Recording.2023-08-24.at.18.46.48.mov |
I tried with a simple sync case, Test code: from tqdm import tqdm
import time
import random
for leave in [True, None, False]:
print('Leave: ', leave)
print('-------------------')
bars = [tqdm(total=1024, unit="B", unit_scale=True, leave=leave, unit_divisor=1024, ncols=100, position=i) for i in range(0, 5)]
size = int(1024*1024*10*random.random())
for i, bar in enumerate(bars):
bar.desc = f'Bar {i + 1}/5'
bar.reset(total=size)
offset = 0
while True:
if offset < size:
update_chunk = 1024*200
time.sleep(.1)
offset += update_chunk
if offset > size:
update_chunk -= offset - size
for bar in bars:
bar.update(update_chunk)
else:
break
for bar in bars:
bar.close()
print('Done!')
print('-------------------') Output with 4.66.1 release:
Output with tqdm-4.66.2.dev2+gbf765f3 (this PR):
Issues with release:
Issues with this PR:
|
Your comment in #1496:
do inspire me a quick fix for my case: Just do for bar in reversed(bars):
bar.close() And now both the release and your PR works flawlessly |
Thanks for providing additional tests! This is really helpful.
Ah, yes, that'd be a bug because in that case only the first bar should be left. But because my change causes other bars to be moved to position
Ah, when moving up bars they now leave a ghost. I added a Here is my updated reproducer, using all three modes: import asyncio
from tqdm.asyncio import trange
async def bar(pos: int, name: str, colour, delay: float, leave: bool | None):
for _ in trange(10, desc=name, colour=colour, position=pos, leave=leave, postfix={"pos": pos}):
await asyncio.sleep(delay)
async def main():
bars = [("A", "green", 0.1), ("B", "cyan", 0.6), ("C", "yellow", 0.25), ("D", "magenta", 0.4)]
for leave in (None, False, True):
print("Leave:", leave)
tasks = [bar(pos, *args, leave) for pos, args in enumerate(bars)]
await asyncio.gather(*tasks)
print("Done!")
asyncio.run(main()) and the output this produces: Screen.Recording.2023-08-25.at.14.40.25.movI did notice that there is a race condition that affects one of the tests I added,
but I can't figure out why this would be the case as every |
5fa739e
to
b205dd1
Compare
When a bar is closed it is moved to pos 0, which means all the other bars below it must now be given a new position number to have their output still go to the same screen line.
b205dd1
to
07c1559
Compare
Is this fix still in progress? Would be greatly appreciated as the 'ghost' progress bars cause a lot of user confusion. I am unable to help with development but could test if that is helpful. |
When a bar is closed it is moved to pos 0, which means all the other
bars below it must now be given a new position number to have their
output still go to the same screen line.
Fixes #1305, #1331, #1496
Less important but also useful:
read the known issues
environment, where applicable: