Is there any way to get a textual progress bar (e.g. like the progressbar module in a python repl) when working in console mode?
Anything would be better than this:
Mathematica Stack Exchange is a question and answer site for users of Wolfram Mathematica. It only takes a minute to sign up.
Sign up to join this communityHere is a crude progress bar demo script that has been tested in a Gnome terminal under Linux and a Powershell command prompt under Windows 10. Don't expect much because it's only a loop with a print statement:
progbar[width_, title_] := Function[{ndx},
Print[ " " <> title<>"\n [" <>
StringJoin@ConstantArray["*", ndx] <>
StringJoin@ConstantArray[" ", width-ndx] <>
"]" <> ToString[Round[100*ndx/width,1]] <>
"% \n\033[3A" ]
]
nsteps = 30;
pb = progbar[nsteps, "Crude Progress Bar"]
Table[ (* put the function steps here *)
Pause[1];
(* follow the function steps with this one-line progress bar printer *)
pb[ndx],
{ndx, nsteps}
]
Print["\n\n"]
Crude Progress Bar
[******************************]100%
So what's going on? The progbar[ ]
function returns a function that prints the progress bar. It takes 2 arguments. width
is total number of steps, which should be an integer between, say, 10 and 100. title
is the message to printed above the progress bar.
The pb = progbar[ ... ]
statement means pb
will be called with the actual progress, probably a step number, between zero and width
. The variable name width
makes sense in progbar
, but the user might think of it as nsteps
.
To monitor the training or testing of a machine learning algorithm, say, divide the training (or testing) task into chunks. The number of chunks will be width
, or nsteps
in the above demo. Perform the task in a loop and call pb
with the loop index after each training with each chunk of data. The above demo uses Pause[1]
to represent the training (or testing) task.
What's the trick? The only trick is to use an ANSI escape code to Print
on the same line every time. The ANSI code "ESC[ 3 A" moves the cursor up 3 lines. There are many ANSI escape codes. This one is an example of a Terminal Output Sequence.
The Print["\n\n"]
command is used to get the cursor back down below the progress bar after the task loop completes.
This has not been thoroughly tested, but one bug is known. If we run the demo script like this clear ; wolframscript -f progbardemo.wls
, it will be too close to the top edge of the terminal. So, clear
the terminal and then enter the wolframscript -f progbardemo.wls
.
EDIT 1:
The appearance of the progress bar could be improved if escape codes that turn the screen cursor on and off could be found. The appearance could also be improved by judicious use of the well-known escape codes for color.
The progress bar does no error checking, so the user must ensure the argument of pb
is an integer in the range of zero to width
. Here is an example of a random walk that uses the progress bar as an indicator widget. Sometimes the walker wanders too far, and sometimes it comes back within range. Error checking is done by "normalizing" the progress before.
nsteps = 50;
pb = progbar[nsteps, "Random Walker"]
progress = nsteps/2;
Do[
progress += RandomChoice[{-1,1}/100];
normal = Max[Min[Round[progress], nsteps], 0];
pb[normal],
{10000000}
]
Print["\n\n"]
EDIT 2: Improving the Appearance
The progress bar's appearance will be improved under some circumstances by hiding the screen cursor. Use Print["\033[?25l"]
before the loop to conceal the cursor and use Print["\033[?25h"]
after the loop to reveal the cursor. If the loop should fail for some reason, the code that reveals the cursor may not be evaluated. If the WL script quits without revealing the cursor, the user will see the normal command line prompt, but without a cursor. It may be possible to execute python -c "print('\033[?25h')"
at the command prompt to reveal the cursor. In Linux there is also a tset
command that will reveal the screen cursor.
Monitor
doesn't seem to be supported either andPrintTemporary
isn't exactly the answer. Just a comment. $\endgroup$