Ever wondered where your lengthy processing was in, and when would it finish? Ever found yourself hitting [RETURN] now and then to ensure it didn't hang, or if in a remote SSH session the connection was still working? Ever needed to pause some processing for a while, return to the Python prompt for a manual inspection or fixing an item, and then resume the process seamlessly? I did...
I've started this cool progress bar thinking about all that, the alive-progress!
I like to think of it as a new kind of progress bar for Python, since it has among other things:
.check()
tools in both bars and spinners, to help you design your animations! You can see all the frames and cycles exploded on screen, with several verbosity levels, even including an alive rendition!
This is a major breakthrough in alive-progress
!
I took 1 year developing it, and I'm very proud of what I've accomplished \o/
.check()
tools, that compile and beautifully render all frames from all animation cycles of spinners and bars! they can even include complete frame data, internal codepoints and even their animations!
alive-progress
widgets!alive_it
, that accepts an iterable and calls bar()
for you!Since this is a major version change, direct backward compatibility is not guaranteed. If something does not work at first, just check the new imports and functions' signatures, and you should be good to go. All previous features should still work here!
��
This README was completely rewritten, so please take a full look to find great new details!!
Just install with pip:
❯ pip install alive-progress
Want to see it gloriously running in your system before anything?
❯ python -m alive_progress.tools.demo
Cool huh?? Now enter an ipython
REPL and try it yourself:
from alive_progress import alive_bar
import time
for x in 1000, 1500, 700, 0:
with alive_bar(x) as bar:
for i in range(1000):
time.sleep(.005)
bar()
You'll see something like this, with cool animations throughout the process
|████████████████████████████████████████| 1000/1000 [100%] in 5.8s (171.62/s)
|██████████████████████████▋⚠︎ | (!) 1000/1500 [67%] in 5.8s (172.62/s)
|████████████████████████████████████████✗︎ (!) 1000/700 [143%] in 5.8s (172.06/s)
|████████████████████████████████████████| 1000 in 5.8s (172.45/s)
Nice huh? Loved it? I knew you would, thank you
To actually use it, just wrap your normal loop in an alive_bar
context manager like this:
with alive_bar(total) as bar: # declare your expected total
for item in items: # <<-- your original loop
print(item) # process each item
bar() # call `bar()` at the end
And it's alive!
So, in short: retrieve the items as usual, enter the alive_bar
context manager with the number of items, and then iterate/process those items, calling bar()
at the end! It's that simple! :)
items
can be any iterable, like for example a queryset;alive_bar
is the expected total, like qs.count()
for querysets, len(items)
for iterables with length, or even a static number;bar()
is what makes the bar go forward — you usually call it in every iteration, just after finishing an item;bar()
too much (or too few at the end), the bar will graphically render that deviation from the expected total
, making it very easy to notice overflows and underflows;bar.current()
.You can get creative! Since the bar only go forward when you call
bar()
, it is independent of the loop! So you can use it to monitor anything you want, like pending transactions, broken items, etc, or even call it more than once in the same iteration! So, at the end, you'll get to know how many of those "special" events there were, including their percentage in relation to the total!
While inside an alive_bar
context, you can effortlessly display messages with:
print()
statement, where alive_bar
nicely cleans up the line, prints your message alongside the current bar position at the time, and continues the bar right below it;logging
framework, including file outputs, are also enriched exactly like the previous one;bar.text('message')
, which sets a situational message right within the bar, where you can display something about the current item, or the phase the processing is in!You now have a quicker way to monitor anything! Here, the items are automatically tracked for you!
Behold the alive_it
=> the alive_bar
iterator adapter!
Simply wrap your items with it, and loop over them as usual!
The bar will just work, it's that simple!
from alive_progress import alive_it
for item in alive_it(items): # <<-- wrapped items
print(item) # process each item
HOW COOL IS THAT?!
All alive_bar
parameters apply but total
, which is smarter (if not supplied it will be auto-inferred from your data using len
or length_hint
), and manual
that does not make sense here.
Note there isn't any bar
handle at all in there. But what if you do want it, for example to set text messages or retrieve the current progress?
You can interact with the internal alive_bar
by just assigning alive_it
to a variable, like this:
bar = alive_it(items): # <<-- bar with wrapped items
for item in bar: # <<-- iterate on bar
print(item) # process each item
bar.text(f'ok: {item}') # WOW, it works!
Note that this is a slightly special bar
, which does not support bar()
, since the iterator adapter tracks items automatically for you.
Please do mind their differences:
- the full use is
with alive_bar() as bar
, where you iterate and callbar()
whenever desired;- the basic adapter use is
for item in alive_it(items)
, where items are automatically tracked;- the named adapter use is
bar = alive_it(items)
, where, besides items being automatically tracked, you get a special iterablebar
to customize.
Actually, the total
argument is optional. If you do provide it, the bar enters in definite mode, the one used for well-bounded tasks. This mode has all the widgets alive-progress
has to offer: count, throughput and ETA.
If you don't, the bar enters in unknown mode, the one used for unbounded tasks. In this mode the whole progress bar is animated, as it's not possible to determine the percentage, and therefore the ETA. But you still get the count and throughput widgets as usual.
The cool spinner is still present here besides the progress bar, both running their own animations concurrently and independently of each other, rendering a unique show in your terminal!
As a matter of fact, definite and unknown modes both use a core strategy with a counter to maintain progress. This is the source value from which all widgets are derived.
On the other hand, manual mode uses a core strategy with a percentage progress. This enables you to get complete control of the bar position! It's usually used to monitor processes that only feed you the percentage of completion, or to generate some kind of special effect.
To use it, just include a manual=True
argument into alive_bar
(or config_handler
), and you get to send your own percentage to the bar()
handler! For example to set it to 15%, you just call bar(0.15)
— which is 15 / 100.
You can also use total
here! If you do provide it, the bar
will infer an internal counter, and thus you also get the count, throughput and ETA widgets!
If you don't, it's not possible to infer any counter, but you'll at least get rough versions of the throughput and ETA widgets! The throughput will use "%/s" (percent per second), and the ETA will be until 1 (100%). Both are very inaccurate, but are better than nothing.
You can call
bar
in manual mode as frequently as you want! The refresh rate will still be asynchronously computed as usual, according to the current progress and the elapsed time, so you won't ever spam the terminal with more updates than it can handle.
bar()
handlersThe bar()
handlers support either relative or absolute semantics, depending on the mode:
bar()
to increment count by one, or send any other positive increment like bar(5)
to increment those in one step;bar(0.35)
to instantly put the bar in 35% — this argument is mandatory here!The manual mode enables you to get super creative! Since you can set the bar instantly to whatever position you want, you could:
- make it go backwards — perhaps to graphically display the timeout of something;
- create special effects — perhaps to act like a real time gauge of some sort.
In any mode, to retrieve the current count/percentage, just call: bar.current()
:
When total
is provided all is cool:
mode | counter | percentage | throughput | ETA | over/underflow |
---|---|---|---|---|---|
definite |
|
|
|
|
|
manual |
|
|
|
|
|
When it isn't, some compromises have to be made:
mode | counter | percentage | throughput | ETA | over/underflow |
---|---|---|---|---|---|
unknown |
|
|
|
|
|
manual |
|
|
|
|
|
It's actually quite simple, you do not need to think about which mode you should use:
Just always send the total
if you have it, and use manual
if you need it!
It will just work the best it can!
Maintaining an open source project is hard and time-consuming.
I put much
If you've appreciated my work and would like me to continue improving it, please back me up with a donation!
I'd appreciate any encouragement
Wondering what styles are builtin? It's showtime
! ;)
from alive_progress.styles import showtime
showtime()
Actually I've made these styles just to try the factories I've created, but I think some of them ended up very very cool! Use them at will, mix them to your heart's content!
The showtime
exhibit have an optional argument to choose which show to present, Show.SPINNERS
(default), Show.BARS
or Show.THEMES
, take a look at each of them! ;)
(
The showtime
exhibit also accepts some customization options:
For example to get a marine show, you can showtime(pattern='boat|fish|crab')
:
You can also access these shows with the shorthands
show_bars()
,show_spinners()
, andshow_themes()
!
There's also a small utility called
print_chars()
, to help finding that cool character to put in your customized spinners or bars, or to determine if your terminal do support unicode characters.
There are several options to customize both appearance and behavior!
All of them can be set both directly in the alive_bar
or globally in the config_handler
!
These are the options - default values in brackets:
title
: an optional, always visible bar titlelength
: [40
] the number of characters to render the animated progress barspinner
: the spinner style to be rendered next to the barbar
: the bar style to be rendered in known modesunknown
: the bar style to be rendered in the unknown modetheme
: ['smooth'
] a set of matching spinner, bar and unknownforce_tty
: [None
] forces animations to be on, off, or according to the tty (more details here)manual
: [False
] set to manually control the bar positionenrich_print
: [True
] enriches print() and logging messages with the bar positionreceipt_text
: [False
] set to repeat the last text message in the final receiptmonitor
: [True
] set to display the monitor widget 123/100 [123%]
stats
: [True
] set to display the stats widget (123.4/s eta: 12s)
elapsed
: [True
] set to display the elapsed time widget in 12s
title_length
: [0
] fixes the title lengths, or 0 for unlimitedspinner_length
: [0
] forces the spinner length, or 0
for its natural oneAnd there's also one that can only be set locally in an alive_bar
context:
calibrate
: maximum theoretical throughput to calibrate animation speed (more details here)To set them locally, just send them as keyword arguments to alive_bar
:
with alive_bar(total, title='Processing', length=20, bar='halloween'):
...
To use them globally, send them to config_handler
, and any alive_bar
created after that will include those options! And you can mix and match them, local options always have precedence over global ones:
from alive_progress import config_handler
config_handler.set_global(length=20, spinner='wait')
with alive_bar(total, bar='blocks', spinner='twirls'):
# the length is 20, the bar is 'blocks' and the spinner is 'twirls'.
...
Yes, you can assemble your own spinners! And it's easy!
I've created a plethora of special effects, so you can just mix and match them any way you want! There are frames, scrolling, bouncing, sequential, alongside and delayed spinners! Get creative!
The spinners' animations are engineered by very advanced generator expressions, deep within several layers of meta factories, factories and generators
alive_bar
and config_handler
;These generators are capable of multiple different animation cycles according to the spinner behavior, e.g. a bouncing spinner with a simple pattern argument runs one cycle to smoothly bring a subject into the scene, then repeatedly reposition it until the other side, then make it smoothly disappear of the scene => this is all only one cycle! Then it is followed by another cycle to make it all backwards. But the same bouncing spinner accepts repeating patterns in both right and left directions, which generates the cartesian product of all combinations, thus capable of producing dozens of different cycles!!
And there's more! They only yield the next animation frame until the current cycle is exhausted, then stops! The next cycle does not start just yet! It creates natural breaks, in exactly the correct spots, where the animations would not be disrupted, and I can smoothly restart whatever generator I want!!
That has all kinds of cool implications: the cycles can have different frame counts, different screen lengths, they do not need to be synchronized, they can create long different sequences by themselves, they can cooperate with each other to play cycles in sequence or alongside, and I can amaze you displaying several animations at the same time on the screen without any interferences!
It's almost like they were... alive! ==> Yes, that's where this project's name came from!
Now these generators of cycles and frames are fully consumed ahead of time by the Spinner Compiler! This is a very cool new processor that I made inside the Cell Architecture effort, to make all these animations work even in the presence of wide chars or complex grapheme clusters! It was very hard to make these clusters smoothly and gradually enter and exit frames without breaking everything, because several chars can in fact represent only one visible symbol!! So they cannot ever be split, they have to enter and exit the scene always all at once or the grapheme won't show (an Emoji for instance)!! Enter the Spinner Compiler......
This has made possible some incredible things!! Since this Compiler generates the whole spinner frame data beforehand (the generators are actually infinite, but I've made them provide statistics about themselves), the animations do not need to be calculated anymore, those grapheme fixes can be applied only once, and I can just collect all that frame data unhindered, ready to play animations for this environment, so no runtime overhead at all!!
Also, with the full frame data available, I could create several commands to refactor that data, like changing shapes and replacing chars, including visual pauses (frame repetitions), generating bouncing effects on demand over any content, and even transposing cycles with frames!!
But how can you see these effects? Does the effect you created look good? Or is not working as you thought? Now you can see all generated cycles and frames analytically, in a very beautiful rendition!!
I love what I've achieved here
check
tool!!
It's awesome, if I say so myself, isn't it? And a very complex piece of software I'm proud of, take a look at its code if you're curious.
The check
tool is much more powerful! For instance, you can see the codepoints of the frames!!! And maybe have a glimpse of why this version was so so very hard and complex to make...
In red you see the grapheme clusters, that occupy one or two "logical positions", regardless of their actual sizes... These are the "Cells" of the new Cell Architecture...
Look how awesome an Emoji Flag is represented:
The flag seems to move so smoothly because it uses "half-characters"! Since it is a wide char, alive-progress
knows it will be rendered with "two visible chars", and the animations consider this, but compose with spaces, which occupy only one. When one uses mixed backgrounds, the situation is much more complex...
The types of factories I've created are:
frames
: draws any sequence of characters at will, that will be played frame by frame in sequence;scrolling
: generates a smooth flow from one side to the other, hiding behind or wrapping upon invisible borders — allows using subjects one at a time, generating several cycles of distinct characters;bouncing
: similar to scrolling
, but makes the animations bounce back to the start, hiding behind or immediately bouncing upon invisible borders;sequential
get a handful of factories and play them one after the other sequentially! allows to intermix them or not;alongside
get a handful of factories and play them alongside simultaneously, why choose when you can have them all?! allows to choose the pivot of the animation;delayed
: get any other factory and copy it multiple times, increasingly skipping some frames on each one! very cool effects are made here!For more details please look at their docstrings, which are very complete.
Customizing bars is nowhere near that involved. Let's say they are "immediate", passive objects. They do not support animations, i.e. it will always generate the exact same rendition given the same parameters. Remember spinners are infinite generators, capable of generating long and complex sequences.
Well, bars also have a meta factory, use closures to store the styling parameters, and receive additional operating parameters, but then the actual factory can't generate any content by itself. It still needs an additional floating point number between 0 and 1, the percentage to render itself, everytime it's needed.
The
alive_bar
calculates and provides this percentage automatically to it, but you can send it yourself with themanual
mode!
Bars also do not have a Bar Compiler, but they do provide the check tool!!
You can even mix and match wide chars and normal chars! Just like spinners do!
Use and abuse the check tools!! They have more modes, there's even real time animations!
Create the wildest and coolest animations you can, and send them to me!
I'm thinking about creating some kind ofcontrib
package, with user contributed spinners and bars!
Wow, if you read everything till here, you should now have a sound knowledge about using alive-progress
!
And if you want to know even more, exciting stuff lies ahead!
Maintaining an open source project is hard and time-consuming.
I put much
If you've appreciated my work and would like me to continue improving it, please back me up with a donation!
I'd appreciate any encouragement
So, you need to monitor a fixed operation, without any loops?
It'll work for sure! Here is an example (although a naive approach, we'll do better):
with alive_bar(4) as bar:
corpus = read_file(file)
bar() # file was read, tokenizing
tokens = tokenize(corpus)
bar() # tokens generated, processing
data = process(tokens)
bar() # process finished, sending response
resp = send(data)
bar() # we're done! four bar calls with `total=4`
It's naive because it considers all steps are equal, but actually each one may take a very different time to complete. Think a read_file
and a tokenize
steps being extremely fast, making the percentage skyrocket to 50%, then stopping for a long time in the process
step. You get the point, it can ruin the user experience and create a very misleading ETA.
What you need to do is distribute the steps accordingly! Since you told alive_bar
there were four steps, when the first one completed it understood 1/4 or 25% of the whole processing was complete, which as we've seen may not be the case. Thus, you need to measure how long your steps do take, and use the manual mode to increase the bar percentage by different amounts at each step!
You can use my other open source project about-time to easily measure these durations! Just try to simulate with some representative inputs, to get better results. Something like:
from about_time import about_time
with about_time() as t_total: # this about_time will measure the whole time of the block.
with about_time() as t1 # the other four will get the relative timings within the whole.
corpus = read_file(file) # `about_time` supports several calling conventions, including one-liners.
with about_time() as t2 # see its documentation for more details.
tokens = tokenize(corpus)
with about_time() as t3
data = process(tokens)
with about_time() as t4
resp = send(data)
print(f'percentage1 = {t1.duration / t_total.duration}')
print(f'percentage2 = {t2.duration / t_total.duration}')
print(f'percentage3 = {t3.duration / t_total.duration}')
print(f'percentage4 = {t4.duration / t_total.duration}')
There you go! Now you know the relative timings of all the steps, and can use them to improve your original code! Just get the cumulative timings and put within a manual mode alive_bar
!
For example, if the timings you found were 10%, 30%, 20% and 40%, you'd use 0.1, 0.4, 0.6 and 1. (the last one should always be 1.):
with alive_bar(4, manual=True) as bar:
corpus = read_big_file()
bar(0.1) # 10%
tokens = tokenize(corpus)
bar(0.4) # 30% + 10% from previous steps
data = process(tokens)
bar(0.6) # 20% + 40% from previous steps
resp = send(data)
bar(1.) # always 1. in the last step
That's it! The user experience and ETA should be greatly improved now.
So, you want to calibrate the engine?
The alive-progress
bars have a cool visual feedback of the current throughput, so you can actually see how fast your processing is, as the spinner runs faster or slower with it.
For this to happen, I've put together and implemented a few fps curves to empirically find which one gave the best feel of speed:
(interactive version [here](https://www.desmos.com/calculator/ema05elsux))
The graph shows the logarithmic (red), parabolic (blue) and linear (green) curves, these are the ones I started with. It was not an easy task, I've made hundreds of tests, and never found one that really inspired that feel of speed I was looking for. The best one was the logarithmic one, but it reacted poorly with small numbers.I know I could make it work with a few twists for those small numbers, so I experimented a lot and adjusted the logarithmic curve (dotted orange) until I finally found the behavior I expected. It is the one that seemed to provide the best all around perceived speed changes throughout the whole spectrum from units to billions.That is the curve I've settled with, and it's the one used in all modes and conditions. In the future and if someone would find it useful, that curve could be configurable.
Well, the default alive-progress
calibration is 1,000,000 in bounded modes, i.e., it takes 1 million iterations per second for the bar to refresh itself at 60 frames per second. In the manual unbounded mode it is 1.0 (100%). Both enable a vast operating range and generally work really well.
For example, take a look at the effect these very different calibrations have, running the very same code at the very same speed! Notice the feel the spinner passes to the user, is this processing going slow or going fast? And remember that isn't only the spinner refreshing but the whole line, complete with the bar rendition and all widgets, so everything gets smoother or sluggish:
So, if your processing hardly gets to 20 items per second, and you think
alive-progress
is rendering sluggish, you could increase that sense of speed by calibrating it to let's say40
, and it will be running waaaay faster... Actually it is better to leave some headroom and calibrate it to something between 50% and 100% more, and then tweak it from there to find the one you like the most! :)
Oh you want to stop it altogether!
Why would you want to pause it, I hear? To get to manually act on some items at will, I say!
Suppose you need to reconcile payment transactions (been there, done that). You need to iterate over thousands of them, detect somehow the faulty ones, and fix them. This fix is not simple nor deterministic, you need to study each one to understand what to do. They could be missing a recipient, or have the wrong amount, or not be synced with the server, etc, it's hard to even imagine all possibilities. Typically you would have to let the detection process run until completion, appending to a list each inconsistency found, and waiting potentially a long time until you can actually start fixing them. You could of course mitigate that by processing in chunks or printing them and acting in another shell, but those have their own shortcomings.
Now there's a better way, pause the actual detection for a moment! Then you have to wait only until the next fault is found, and act in near real time!
To use the pause mechanism you must be inside a function, to enable the code to yield
the items you want to interact with. You should already be using one in your code, but in the ipython shell for example, just wrap the alive_bar
context inside one. Then you just need to enter the bar.pause()
context!! Something like with bar.pause(): yield transaction
.
def reconcile_transactions():
qs = Transaction.objects.filter() # django example, or in sqlalchemy: session.query(Transaction).filter()
with alive_bar(qs.count()) as bar:
for transaction in qs:
if not validate(transaction):
with bar.pause(): yield transaction
bar()
That's it! Then you can use it in any code or even ipython! Just call the reconcile function to instantiate the generator and assign it to gen
for example, and whenever you want another transaction to fix, call next(gen, None)
! The progress bar will pop in as usual, but as soon as an inconsistency is found, the bar pauses itself and you get the prompt back with a transaction! It's almost magic!
In [11]: gen = reconcile_transactions()
In [12]: next(gen, None)
|█████████████████████ | 105/200 [52%] in 5s (18.8/s, eta: 4s)
Out[12]: Transaction<#123
You can then use _12
ipython's shortcut to get the transaction, if you don't like that just assign it with trn = next(gen, None)
, and you're set up as well to fix that trn
at once!
When you're done, revive the detection process with the same next
as before... The bar reappears exactly like it had stopped and continues on the next item like nothing happened!! Nice huh :)
In [21]: next(gen, None)
|█████████████████████ | ▁▃▅ 106/200 [52%] in 5s (18.8/s, eta: 4s)
Those astonishing animations refuse to display?
There are ttys that do not report themselves as "interactive", which are valid for example in shell pipelines "|" or headless consoles. But there are some that do that for no good reason, like Pycharm's python console for instance. And if a console is not interactive, alive_bar
disables all animations and refreshes, only printing the final receipt. This is made to avoid spamming a log file or messing up a pipe output with hundreds of refreshes.
So if you are in an interactive environment, like the aforementioned Pycharm console, you can see alive_bar
in all its glory! Just use the force_tty
argument!
with alive_bar(1000, force_tty=True) as bar:
for i in range(1000):
time.sleep(.01)
bar()
You can also set it system-wide using the config_handler
, then you won't need to pass it manually anymore.
Do note that Pycharm's console is heavily instrumented and thus has more overhead, so the outcome may not be as fluid as one would expect. To see alive_bar
animations perfectly, always prefer a full-fledged terminal.
(
�� new) Nowforce_tty
also supportsFalse
, which will disable animations even on interactive displays.
alive-progress
hadn't had any dependency. Now it has two: one is about-time (another very cool project of mine, if I say so myself), to track the spinner compilation times and generate its human friendly renditions. The other is grapheme, to detect grapheme cluster breaks (I've opened an issue there asking about the future and correctness of it, and the author guarantees he intends to update the project on every new Unicode version);alive-progress
hadn't had a single Python class! Now it has two tiny ones, for very specific reasons (change callables and iterator adapter). I've used Closures extensively here, to create factories and persist parameters, and even alive_bar
itself is a function, where I dynamically plug other ones (Python functions have a __dict__
just like classes do).
- create an unknown mode for bars (without a known total and eta)
- implement a pausing mechanism
- change spinner styles
- change bar styles
- include a global configuration system
- create customizable generators for scrolling, bouncing, delayed and compound spinners
- create an exhibition for spinners and bars, to see them all in motion
- include theme support in configuration
- soft wrapping support
- hiding cursor support
- python logging support
- exponential smoothing of ETA time series
- create an exhibition for themes
The alive_progress
framework starting from version 2.0 does not support Python 2.7 and 3.5 anymore.
If you still need support for them, you can always use the versions 1.x, which are also full-featured and do work very well, just:
❯ pip install -U "alive_progress<2"
If you put this version as a dependency in a requirements.txt file, I strongly recommend to put
alive_progress<2
, as this will always fetch the latest release of the v1.x series. That way, if I ever release a bugfix for it, you will get it the next time you install it.
.check()
tools in both spinners and bars; bars and spinners engines revamp; new animation modes in alongside and sequential spinners; new builtin spinners, bars and themes; dynamic showtime with themes, scroll protection and filter patterns; improved logging for files; several new configuration options for customizing appearance; new iterator adapter alive_it
; uses time.perf_counter()
high resolution clock; requires python 3.6+ (and officially supports python 3.9 and 3.10)bar.current()
method; newlines get printed on vanilla Python REPL; bar is truncated to 80 chars on Windows.bar.text()
method, to set situational messages at any time, without incrementing position (deprecates 'text' parameter in bar()
); performance optimizationsbackground
parameter instead of blank
, which accepts arbitrarily sized strings and remains fixed in the background, simulating a bar going "over it"show_spinners
and show_bars
, new utility print_chars
, show_bars
gains some advanced demonstrations (try it again!)This software is licensed under the MIT License. See the LICENSE file in the top distribution directory for the full license text.
Maintaining an open source project is hard and time-consuming.
I put much
If you've appreciated my work and would like me to continue improving it, please back me up with a donation!
I'd appreciate any encouragement
目录 1、Progress库 2、tqdm库 3、alive-progress库 4、PySimpleGUI库 在项目开发过程中加载、启动、下载项目难免会用到进度条,如何使用Python实现进度条呢? 这里为小伙伴们分享四种Python实现进度条的库:Progress库、tqdm库、alive-progress库和PySimpleGUI库,其中前三个是文本进度条库,最后一个是可以在GUI上运行的
2021-11-30 测试通过 非原创,原文来自知乎用户【Python与数据挖掘】,转载备忘 原文链接:https://zhuanlan.zhihu.com/p/403641309 1. 简介 tqdm:可在终端应用程序中使用,也可以配合 Jupyter Notebook 或 Jupyter Lab 使用,更为 Pandas 提供了支持。 alive-progress:进度条花样繁多,但目前只能在
进度条的库:alive-progress 知乎:链接 github 项目地址:链接 安装: pip install alive-progress 简单示例: # 导入 alive-progress 库 from alive_progress import alive_bar import time # 使用 with 语句创建一个进度条 with alive_bar(100, force_tt
简单进度条打印 from alive_progress import alive_bar import time with alive_bar(3000) as bar: for i in range(3000): bar() time.sleep(0.01) 下载任务 from alive_progress import alive_bar impor
我们先导入alive_progress库 from alive_progress import alive_bar 然后是计算圆周率的核心部分。我用的是马青公式,具体可以自己在网上查找 '''算法根据马青公式计算圆周率''' num = 10000 # 计算小数点后的多少位 # 多计算10位,防止尾数取舍的影响 number1 = num + 10 # 算到小数点后number1位 b = 10
众所周知v-Progress标签是一个进度条展示百分比效果的组件,那么如何实现根据百分比的大小来自动切换颜色呢?具体实现代码如下: <template v-if="col.columnLabel === '项目进度'"> <div v-if="scope.row[col.columnName]<='10'" class="abcLis
项目会使用tab功能,进而需要对页面数据进行缓存。在本地开发的时候,能够正常缓存,但是在使用webpack打包后,上传至服务器发现缓存失效,导致有些业务出错。 路由代码:module.exports = (file: string) => { 'use strict'; return () => import(`@/views/${file}`); };const getComponent =
当您使用简单的cp命令在没有标志的情况下复制终端中的大文件时,您有时可能会怀疑它是否真的在复制或者进程被某种方式阻止,它实际上永远不会完成。 输出不存在,您很想按Ctrl-C结束中止进程。 那么,您可以在另一... >   VMAX:1)用备份软件把bcv lun从需求的磁带恢复到某个日期。2)bcv 和 std做反向同步: symclone -g restore3) split生产数据就
python程序报错: from progress.bar import Bar ModuleNotFoundError: No module named 'progress' 解决办法: pip install progress 具体参考网页:https://pypi.org/project/progress/
非标准 这个功能是非标准的,不在标准轨道上。不要在面向 Web 的生产站点上使用它:它不适用于每个用户。实现之间也可能存在很大的不兼容性,并且行为在未来可能会发生变化。 Keep-Alive一般报头允许发送者提示关于如何连接,并且可以被用于设置超时时间,并且请求的最大数量。 Connection头需要被设置为“保活”这个标题有任何意义。此外,Connection和Keep-Alive在 HTTP
Props: include - 字符串或正则表达式。只有匹配的组件会被缓存。 exclude - 字符串或正则表达式。任何匹配的组件都不会被缓存。 用法: <keep-alive> 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。和 <transition> 相似,<keep-alive> 是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在父组件链中。 当组件在 <keep-
然而我这样做,似乎并不奏效: 您知道如何使DefaultHttpClient使用TCP保持活动策略吗?
1. 前言 本小节我们将介绍 Vue 的动态组件以及缓存 keep-alive 的使用。包括动态组件的使用方法,以及如何使用 keep-alive 实现组件的缓存效果。 2. 慕课解释 动态组件是让多个组件使用同一个挂载点,并动态切换。动态组件是 Vue 的一个高级用法,但其实它的使用非常简单。keep-alive 是 vue 的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染 DOM
本文向大家介绍Vue keep-alive实践总结(推荐),包括了Vue keep-alive实践总结(推荐)的使用技巧和注意事项,需要的朋友参考一下 <keep-alive>是Vue的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM。 <keep-alive> 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。和 <transition> 相似,<keep-alive>
问题内容: 继续我提出的问题”如何实现ExecutorService以基于轮换的方式执行任务?”),我试图在我的代码库中使用ThreadPoolExecutor。即使反复尝试从Java API文档中了解,我仍然无法清楚地理解要在构造函数中传递的参数的功能/目的。希望有人可以通过一些很好的例子向我解释。 Java文档摘录: - 当线程数大于内核数时,这是多余的空闲线程将在终止之前等待新任务的最长时间