Git Product home page Git Product logo

progressmeter.jl's Introduction

ProgressMeter.jl

Build Status

Progress meter for long-running operations in Julia

Installation

Within julia, execute

using Pkg; Pkg.add("ProgressMeter")

Usage

Progress meters for tasks with a pre-determined number of steps

This works for functions that process things in loops or with map/pmap/reduce:

using Distributed
using ProgressMeter

@showprogress dt=1 desc="Computing..." for i in 1:50
    sleep(0.1)
end

@showprogress pmap(1:10) do x
    sleep(0.1)
    x^2
end

@showprogress reduce(1:10) do x, y
    sleep(0.1)
    x + y
end

The first incantation will use a minimum update interval of 1 second, and show the ETA and final duration. If your computation runs so quickly that it never needs to show progress, no extraneous output will be displayed.

The @showprogress macro wraps a for loop, comprehension, @distributed for loop, or map/pmap/reduce as long as the object being iterated over implements the length method and will handle continue correctly.

using Distributed
using ProgressMeter

@showprogress @distributed for i in 1:10
    sleep(0.1)
end

result = @showprogress desc="Computing..." @distributed (+) for i in 1:10
    sleep(0.1)
    i^2
end

In the case of a @distributed for loop without a reducer, an @sync is implied.

You can also control progress updates and reports manually:

function my_long_running_function(filenames::Array)
    n = length(filenames)
    p = Progress(n; dt=1.0)   # minimum update interval: 1 second
    for f in filenames
        # Here's where you do all the hard, slow work
        next!(p)
    end
end

For tasks such as reading file data where the progress increment varies between iterations, you can use update!:

using ProgressMeter

function readFileLines(fileName::String)
    file = open(fileName,"r")

    seekend(file)
    fileSize = position(file)

    seekstart(file)
    p = Progress(fileSize; dt=1.0)   # minimum update interval: 1 second
    while !eof(file)
        line = readline(file)
        # Here's where you do all the hard, slow work

        update!(p, position(file))
    end
end

The core methods Progress(), ProgressThresh(), ProgressUnknown(), and their updaters are also thread-safe, so can be used with Threads.@threads, Threads.@spawn etc.:

using ProgressMeter
p = Progress(10)
Threads.@threads for i in 1:10
    sleep(2*rand())
    next!(p)
end
finish!(p)

and the @showprogress macro also works

using ProgressMeter
@showprogress Threads.@threads for i in 1:10
    sleep(2*rand())
end
using ProgressMeter
n = 10
p = Progress(n)
tasks = Vector{Task}(undef, n)
for i in 1:n
    tasks[i] = Threads.@spawn begin
        sleep(2*rand())
        next!(p)
    end
end
wait.(tasks)
finish!(p)

Progress bar style

Optionally, a description string can be specified which will be prepended to the output, and a progress meter M characters long can be shown. E.g.

p = Progress(n; desc="Computing initial pass...")

will yield

Computing initial pass...53%|███████████████████████████                       |  ETA: 0:09:02

in a manner similar to python-progressbar.

Also, other properties can be modified through keywords. The glyphs used in the bar may be specified by passing a BarGlyphs object as the keyword argument barglyphs. The BarGlyphs constructor can either take 5 characters as arguments or a single 5 character string. E.g.

p = Progress(n; dt=0.5, barglyphs=BarGlyphs("[=> ]"), barlen=50, color=:yellow)

will yield

Progress: 53%[==========================>                       ]  ETA: 0:09:02

It is possible to give a vector of characters that acts like a transition between the empty character and the fully filled character. For example, definining the progress bar as:

p = Progress(n; dt=0.5,
             barglyphs=BarGlyphs('|','', ['' ,'' ,'' ,'' ,'' ,'', ''],' ','|',),
             barlen=10)

might show the progress bar as:

Progress:  34%|███▃      |  ETA: 0:00:02

where the last bar is not yet fully filled.

Progress meters for tasks with a target threshold

Some tasks only terminate when some criterion is satisfied, for example to achieve convergence within a specified tolerance. In such circumstances, you can use the ProgressThresh type:

prog = ProgressThresh(1e-5; desc="Minimizing:")
for val in exp10.(range(2, stop=-6, length=20))
    update!(prog, val)
    sleep(0.1)
end

Progress meters for tasks with an unknown number of steps

Some tasks only terminate when some non-deterministic criterion is satisfied. In such circumstances, you can use the ProgressUnknown type:

prog = ProgressUnknown(desc="Titles read:")
for val in ["a" , "b", "c", "d"]
    next!(prog)
    if val == "c"
        finish!(prog)
        break
    end
    sleep(0.1)
end

This will display the number of calls to next! until finish! is called.

If your counter does not monotonically increases, you can also set the counter by hand.

prog = ProgressUnknown(desc="Total length of characters read:")
total_length_characters = 0
for val in ["aaa" , "bb", "c", "d"]
    global total_length_characters += length(val)
    update!(prog, total_length_characters)
    if val == "c"
        finish!(prog)
        break
    end
    sleep(0.5)
end

Alternatively, you can display a "spinning ball" symbol by passing spinner=true to the ProgressUnknown constructor.

prog = ProgressUnknown(desc="Working hard:", spinner=true)
while true
    next!(prog)
    rand(1:2*10^8) == 1 && break
end
finish!(prog)

By default, finish! changes the spinner to a , but you can use a different character by passing a spinner keyword to finish!, e.g. passing spinner='✗' on a failure condition:

let found=false
    prog = ProgressUnknown(desc="Searching for the Answer:", spinner=true)
    for tries in 1:10^8
        next!(prog)
        if rand(1:2*10^8) == 42
            found=true
            break
        end
    end
    finish!(prog, spinner = found ? '' : '')
end

In fact, you can completely customize the spinner character by passing a string (or array of characters) to animate as a spinner argument to next!:

prog = ProgressUnknown(desc="Burning the midnight oil:", spinner=true)
while true
    next!(prog, spinner="🌑🌒🌓🌔🌕🌖🌗🌘")
    rand(1:10^8) == 0xB00 && break
end
finish!(prog)

(Other interesting-looking spinners include "⌜⌝⌟⌞", "⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏", "🕐🕑🕒🕓🕔🕕🕖🕗🕘🕙🕚🕛", "▖▘▝▗'", and "▁▂▃▄▅▆▇█".)

Printing additional information

You can also print and update information related to the computation by using the showvalues keyword. The following example displays the iteration counter and the value of a dummy variable x below the progress meter:

x,n = 1,10
p = Progress(n)
for iter in 1:10
    x *= 2
    sleep(0.5)
    next!(p; showvalues = [("iteration count",iter), ("x",x)])
end

In the above example, the data passed to showvalues is evaluated even if the progress bar is not updated. To avoid this unnecessary computation and reduce the overhead, you can alternatively pass a zero-argument function as a callback to the showvalues keyword.

x,n = 1,10
p = Progress(n)
generate_showvalues(iter, x) = () -> [("iteration count",iter), ("x",x)]
for iter in 1:10
    x *= 2
    sleep(0.5)
# unlike `showvalues=generate_showvalues(iter, x)()`, this version only evaluate the function when necessary
next!(p; showvalues = generate_showvalues(iter, x))
end

Showing average time per iteration

You can include an average per-iteration duration in your progress meter by setting the optional keyword argument showspeed=true when constructing a Progress, ProgressUnknown, or ProgressThresh.

x,n = 1,10
p = Progress(n; showspeed=true)
for iter in 1:10
    x *= 2
    sleep(0.5)
    next!(p; showvalues = [(:iter,iter), (:x,x)])
end

will yield something like:

Progress:  XX%|███████████████████████████           |  ETA: XX:YY:ZZ (12.34  s/it)

instead of

Progress:  XX%|███████████████████████████                         |  ETA: XX:YY:ZZ

Conditionally disabling a progress meter

In addition to the showspeed optional keyword argument, all the progress meters also support the optional enabled keyword argument. You can use this to conditionally disable a progress bar in cases where you want less verbose output or are using another progress bar to track progress in looping over a function that itself uses a progress bar.

function my_awesome_slow_loop(n::Integer; show_progress=true)
    p = Progress(n; enabled=show_progress)
    for i in 1:n
        sleep(0.1)
        next!(p)
    end
end

const SHOW_PROGRESS_BARS = parse(Bool, get(ENV, "PROGRESS_BARS", "true"))

m = 100
# let environment variable disable outer loop progress bar
p = Progress(m; enabled=SHOW_PROGRESS_BARS)
for i in 1:m
    # disable inner loop progress bar since we are tracking progress in the outer loop
    my_awesome_slow_loop(i; show_progress=false)
    next!(p)
end

ProgressMeter with additional information in Jupyter

Jupyter notebooks/lab does not allow one to overwrite only parts of the output of cell. In releases up through 1.2, progress bars are printed repeatedly to the output. Starting with release xx, by default Jupyter clears the output of a cell, but this will remove all output from the cell. You can restore previous behavior by calling ProgressMeter.ijulia_behavior(:append). You can enable it again by calling ProgressMeter.ijulia_behavior(:clear), which will also disable the warning message.

Tips for parallel programming

For remote parallelization, when multiple processes or tasks are being used for a computation, the workers should communicate back to a single task for displaying the progress bar. This can be accomplished with a RemoteChannel:

using ProgressMeter
using Distributed

n_steps = 20
p = Progress(n_steps)
channel = RemoteChannel(() -> Channel{Bool}(), 1)

# introduce a long-running dummy task to all workers
@everywhere long_task() = sum([ 1/x for x in 1:100_000_000 ])
@time long_task() # a single execution is about 0.3 seconds

@sync begin # start two tasks which will be synced in the very end
    # the first task updates the progress bar
    @async while take!(channel)
        next!(p)
    end

    # the second task does the computation
    @async begin
        @distributed (+) for i in 1:n_steps
            long_task()
            put!(channel, true) # trigger a progress bar update
            i^2
        end
        put!(channel, false) # this tells the printing task to finish
    end
end

Here, returning some number i^2 and reducing it somehow (+) is necessary to make the distribution happen.

progress_map

More control over the progress bar in a map function can be achieved with the progress_map and progress_pmap functions. The keyword argument progress can be used to supply a custom progress meter.

p = Progress(10, barglyphs=BarGlyphs("[=> ]"))
progress_map(1:10, progress=p) do x
    sleep(0.1)
    x^2
end

Optional use of the progress meter

It possible to disable the progress meter when the use is optional.

x, n = 1, 10
p = Progress(n; enabled = false)
for iter in 1:10
    x *= 2
    sleep(0.5)
    next!(p)
end

In cases where the output is text output such as CI or in an HPC scheduler, the helper function is_logging can be used to disable automatically.

is_logging(io) = isa(io, Base.TTY) == false || (get(ENV, "CI", nothing) == "true")
p = Progress(n; output = stderr, enabled = !is_logging(stderr))

Adding support for more map-like functions

To add support for other functions, ProgressMeter.ncalls must be defined, where ncalls_map, ncalls_broadcast, ncalls_broadcast! or ncalls_reduce can help

For example, with tmap from ThreadTools.jl:

using ThreadTools, ProgressMeter

ProgressMeter.ncalls(::typeof(tmap), ::Function, args...) = ProgressMeter.ncalls_map(args...)
ProgressMeter.ncalls(::typeof(tmap), ::Function, ::Int, args...) = ProgressMeter.ncalls_map(args...)

@showprogress tmap(abs2, 1:10^5)
@showprogress tmap(abs2, 4, 1:10^5)

Development/debugging tips

When developing or debugging ProgressMeter it is convenient to redirect the output to another terminal window such that it does not interfer with the Julia REPL window you are using.

On Linux/macOS you can find the file name corresponding to the other terminal by using the tty command. This file can be opened and passed as the output keyword argument to the Progress/ProgressThresh/ProgressUnknown constructors.

Example

Run tty from the other terminal window (the window where we want output to show up):

$ tty
/dev/pts/3

From the Julia REPL, open the file for writing, wrap in IOContext (to enable color), and pass to the Progress constructor:

io = open("/dev/pts/3", "w")
ioc = IOContext(io, :color => true)
prog = Progress(10; output = ioc)

Output from prog will now print in the other terminal window when executing update!, next!, etc.

Credits

Thanks to Alan Bahm, Andrew Burroughs, and Jim Garrison for major enhancements to this package.

progressmeter.jl's People

Contributors

2005m avatar aaw avatar abahm avatar alyst avatar bicycle1885 avatar burrowsa avatar dependabot[bot] avatar femtocleaner[bot] avatar fredcallaway avatar garrison avatar halleysfifthinc avatar hofmannmartin avatar ianbutterworth avatar ilyaorson avatar jiahao avatar johnnychen94 avatar kristofferc avatar marcmush avatar marius311 avatar martinholters avatar mirkobunse avatar mtsch avatar mweastwood avatar robertfeldt avatar saschatimme avatar stevengj avatar timholy avatar tkelman avatar xukai92 avatar zsunberg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

progressmeter.jl's Issues

LoadError: UndefVarError: stderr not defined

julia> using ProgressMeter
INFO: Precompiling module ProgressMeter.
ERROR: LoadError: UndefVarError: stderr not defined
Stacktrace:
 [1] include_from_node1(::String) at .\loading.jl:576
 [2] include(::String) at .\sysimg.jl:14
 [3] anonymous at .\<missing>:2
while loading C:\Users\user\.julia\v0.6\ProgressMeter\src\ProgressMeter.jl, in expression starting on line 5
ERROR: Failed to precompile ProgressMeter to C:\Users\user\.julia\lib\v0.6\ProgressMeter.ji.
Stacktrace:
 [1] compilecache(::String) at .\loading.jl:710
 [2] _require(::Symbol) at .\loading.jl:497
 [3] require(::Symbol) at .\loading.jl:405

julia> versioninfo()
Julia Version 0.6.2
Commit d386e40c17* (2017-12-13 18:08 UTC)
Platform Info:
  OS: Windows (x86_64-w64-mingw32)
  CPU: Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
  WORD_SIZE: 64
  BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Prescott)
  LAPACK: libopenblas64_
  LIBM: libopenlibm
  LLVM: libLLVM-3.9.1 (ORCJIT, broadwell)

Feature request: support `@showprogress` for function type

Currently, @showprogress doesn't work for functions, e.g.,

function foo(n)
    for i in 1:n
        sleep(0.1)
    end
end
@showprogress foo(50) # The ideal usage, doesn't work

Why we need this?

  • In some situations one does need a silent execution, and in some situations one doesn't.
  • Some package authors don't intend to give any additional execution information other than the results

At present, we could manually do something like this... Not complicated, but this requires some document reading, and when the real kernel function is nested deeply, this requires a bunch of modifications on the APIs.

function foo(n; quite = true)
    p = quite ? nothing : Progress(n)
    for i in 1:n
        sleep(0.1)
        quite ? nothing : next!(p)
    end
end

Take the case of this foo, I think the reason @showprogress won't work for this is because we can't directly get the definition of foo when calling it so that unable to parse the expression. (Ref: JuliaLang/julia#2625, JuliaLang/julia#24347)


I'm wondering if the following alternative procedure is practical to support this feature. (please excuse me for my current status of lacking of experiences in macros, I'm just plotting the general idea)

1. use a @progress macro to generate two functions: a wrapper and a kernel

Let

@progress function foo(n)
    for i in 1:n
        sleep(0.1)
    end
end

generate

function foo_(n)
   quote 
        for i in 1:$n
            sleep(0.1)
        end
    end
end
foo(n) = eval(foo_(n))

By doing this, calling foo(n) is still works as usual -- no Progress is involved. But this gives the possibility to parse the function expressions.

2. write a parser to foo_

Let parse(foo_(50)) returns

quote 
    @showprogress for i in 1:50
        sleep(0.1)
    end
end

3. modify @showprogress to support calling of parse(foo_(50))

let @showprogress foo(50) actually calling eval(parse(foo_(50))), so that this feature is supported


As a summary,

the package author can simply add a @progress notation to support the feature

@progress function foo(n)
# some definitions...
end

and the package user uses @showprogress notation to plot progress

@showprogress foo(50)

This's a solution I think is possible. However, since I'm currently not very familiar with macro writing, I'm not very sure of it.

Simulations that are longer than a day

The counter restarts after a day has passed apparently. This is a feature request for adding days as the maximum unit of time if the simulation takes longer than a day.

Error in combination with @parallel and more than one worker

The following code works fine, as long as only one worker is spawned. I'm using version 0.5.5 and Julia 0.6.3 on Windows.

@everywhere using ProgressMeter
@everywhere n = 10^8
@everywhere p = Progress(n, 1)

sum = @parallel (+) for i = 1:n
    next!(p)
    rand(1:6)
end

println(sum/n)

Spawning just a single additional worker (via addprocs(1)) and running above code, produces the these errors:

Please submit a bug report with steps to reproduce this fault, and any error messages that follow (i
n their entirety). Thanks.
Exception: EXCEPTION_ACCESS_VIOLATION at 0x6b6949c1 -- uv_write at /home/Administrator/buildbot/work
er/package_win64/build/deps/srccache/libuv-d8ab1c6a33e77bf155facb54215dd8798e13825d/src/win\stream.c
:126
while loading no file, in expression starting on line 0
uv_write at /home/Administrator/buildbot/worker/package_win64/build/deps/srccache/libuv-d8ab1c6a33e7
7bf155facb54215dd8798e13825d/src/win\stream.c:126
jl_uv_write at /home/Administrator/buildbot/worker/package_win64/build/src/home/Administrator/buildb
ot/worker/package_win64/build/src\jl_uv.c:414
uv_write at .\stream.jl:798
unsafe_write at .\stream.jl:832
print at .\strings\io.jl:122 [inlined]
printover at C:\Users\julli\.julia\v0.6\ProgressMeter\src\ProgressMeter.jl:311
unknown function (ip: 000000000C5AB596)
jl_call_fptr_internal at /home/Administrator/buildbot/worker/package_win64/build/src/home/Administra
tor/buildbot/worker/package_win64/build/src\julia_internal.h:339 [inlined]
jl_call_method_internal at /home/Administrator/buildbot/worker/package_win64/build/src/home/Administ
rator/buildbot/worker/package_win64/build/src\julia_internal.h:358 [inlined]
jl_apply_generic at /home/Administrator/buildbot/worker/package_win64/build/src/home/Administrator/b
uildbot/worker/package_win64/build/src\gf.c:1926
#updateProgress!#5 at C:\Users\julli\.julia\v0.6\ProgressMeter\src\ProgressMeter.jl:163
unknown function (ip: 000000000C5A7CCF)
jl_call_fptr_internal at /home/Administrator/buildbot/worker/package_win64/build/src/home/Administra
tor/buildbot/worker/package_win64/build/src\julia_internal.h:339 [inlined]
jl_call_method_internal at /home/Administrator/buildbot/worker/package_win64/build/src/home/Administ
rator/buildbot/worker/package_win64/build/src\julia_internal.h:358 [inlined]
jl_invoke at /home/Administrator/buildbot/worker/package_win64/build/src/home/Administrator/buildbot
/worker/package_win64/build/src\gf.c:41
#next!#7 at C:\Users\julli\.julia\v0.6\ProgressMeter\src\ProgressMeter.jl:213
unknown function (ip: 000000000C5A6BF6)
jl_call_fptr_internal at /home/Administrator/buildbot/worker/package_win64/build/src/home/Administra
tor/buildbot/worker/package_win64/build/src\julia_internal.h:339 [inlined]
jl_call_method_internal at /home/Administrator/buildbot/worker/package_win64/build/src/home/Administ
rator/buildbot/worker/package_win64/build/src\julia_internal.h:358 [inlined]
jl_invoke at /home/Administrator/buildbot/worker/package_win64/build/src/home/Administrator/buildbot
/worker/package_win64/build/src\gf.c:41
next! at C:\Users\julli\.julia\v0.6\ProgressMeter\src\ProgressMeter.jl:212
unknown function (ip: 000000000C5A6A1A)
jl_call_fptr_internal at /home/Administrator/buildbot/worker/package_win64/build/src/home/Administra
tor/buildbot/worker/package_win64/build/src\julia_internal.h:339 [inlined]
jl_call_method_internal at /home/Administrator/buildbot/worker/package_win64/build/src/home/Administ
rator/buildbot/worker/package_win64/build/src\julia_internal.h:358 [inlined]
jl_apply_generic at /home/Administrator/buildbot/worker/package_win64/build/src/home/Administrator/b
uildbot/worker/package_win64/build/src\gf.c:1926
macro expansion at Z:\Projekte\julia\d6_parallel.jl:7 [inlined]
#45 at .\distributed\macros.jl:162
unknown function (ip: 000000000C5A68F9)
jl_call_fptr_internal at /home/Administrator/buildbot/worker/package_win64/build/src/home/Administra
tor/buildbot/worker/package_win64/build/src\julia_internal.h:339 [inlined]
jl_call_method_internal at /home/Administrator/buildbot/worker/package_win64/build/src/home/Administ
rator/buildbot/worker/package_win64/build/src\julia_internal.h:358 [inlined]
jl_apply_generic at /home/Administrator/buildbot/worker/package_win64/build/src/home/Administrator/b
uildbot/worker/package_win64/build/src\gf.c:1926
jl_apply at /home/Administrator/buildbot/worker/package_win64/build/src/home/Administrator/buildbot/
worker/package_win64/build/src\julia.h:1424 [inlined]
jl_f__apply at /home/Administrator/buildbot/worker/package_win64/build/src/home/Administrator/buildb
ot/worker/package_win64/build/src\builtins.c:426
#106 at .\distributed\process_messages.jl:268 [inlined]
run_work_thunk at .\distributed\process_messages.jl:56
macro expansion at .\distributed\process_messages.jl:268 [inlined]
#105 at .\event.jl:73
jl_call_fptr_internal at /home/Administrator/buildbot/worker/package_win64/build/src/home/Administra
tor/buildbot/worker/package_win64/build/src\julia_internal.h:339 [inlined]
jl_call_method_internal at /home/Administrator/buildbot/worker/package_win64/build/src/home/Administ
rator/buildbot/worker/package_win64/build/src\julia_internal.h:358 [inlined]
jl_apply_generic at /home/Administrator/buildbot/worker/package_win64/build/src/home/Administrator/b
uildbot/worker/package_win64/build/src\gf.c:1926
jl_apply at /home/Administrator/buildbot/worker/package_win64/build/src/home/Administrator/buildbot/
worker/package_win64/build/src\julia.h:1424 [inlined]
start_task at /home/Administrator/buildbot/worker/package_win64/build/src/home/Administrator/buildbo
t/worker/package_win64/build/src\task.c:267
Allocations: 4022019 (Pool: 4020728; Big: 1291); GC: 8
Worker 2 terminated.ERROR:
LoadError: ProcessExitedException()ERROR (unhandled task failure): EOFError: read end of file

Stacktrace:
 [1] try_yieldto(::Base.##298#299{Task}, ::Task) at .\event.jl:189
 [2] wait() at .\event.jl:234
 [3] wait(::Condition) at .\event.jl:27
 [4] wait(::Task) at .\task.jl:181
 [5] collect(::Base.Generator{Array{Task,1},Base.#wait}) at .\array.jl:470
 [6] preduce(::Function, ::Function, ::UnitRange{Int64}) at .\distributed\macros.jl:148
 [7] include_string(::String, ::String) at .\loading.jl:522
 [8] include_string(::Module, ::String, ::String) at C:\Users\julli\.julia\v0.6\Compat\src\Compat.jl
:88
 [9] (::Atom.##112#116{String,String})() at C:\Users\julli\.julia\v0.6\Atom\src\eval.jl:109
 [10] withpath(::Atom.##112#116{String,String}, ::String) at C:\Users\julli\.julia\v0.6\CodeTools\sr
c\utils.jl:30
 [11] withpath(::Function, ::String) at C:\Users\julli\.julia\v0.6\Atom\src\eval.jl:38
 [12] hideprompt(::Atom.##111#115{String,String}) at C:\Users\julli\.julia\v0.6\Atom\src\repl.jl:67
 [13] macro expansion at C:\Users\julli\.julia\v0.6\Atom\src\eval.jl:106 [inlined]
 [14] (::Atom.##110#114{Dict{String,Any}})() at .\task.jl:80
while loading Z:\Projekte\julia\d6_parallel.jl, in expression starting on line 157

Tag 0.2

Hi Tim,
if possible, could you please tag a new version? especially @showprogress would be great to have without needing Pkg.clone.
Thanks!

Tag a release with parallel support.

Hi all,

I recently added support for map and, more importantly pmap. I think it is a good time to tag a new release. @timholy recently gave me the required permissions for this repo, but I don't know what the procedure is for getting consensus. I guess if no one objects, I will just tag a new version after a week, on 10/5. @garrison @martinholters , you seem to be the biggest contributors. Do you have any comments?

Thanks!

Working with `@parallel`

I've written up a small package (ParallelProgressMeter.jl) for using progress meters with the @parallel macro. It currently uses the slightly clunky syntax @parallelprogress, but I think the original @showprogress macro could be rewritten to incorporate the changes as well.

I should note that most of the inspiration came from PmapProgressMeter.jl.

When using in Sublime IJulia, prints out each message separately

When using in IJulia in sublime the progress bar prints out multiple messages instead on updating a single one. Not sure if this is a Sublime IJulia issue or a ProgressMeter issue but a quick fix if possible would be great.

Computing...  9%|████                                              |  ETA: 0:01:43
Computing... 18%|█████████                                         |  ETA: 0:01:31
Computing... 27%|██████████████                                    |  ETA: 0:01:21
Computing... 36%|██████████████████                                |  ETA: 0:01:12
Computing... 44%|██████████████████████                            |  ETA: 0:01:03
Computing... 53%|███████████████████████████                       |  ETA: 0:00:53
Computing... 62%|███████████████████████████████                   |  ETA: 0:00:44
Computing... 70%|███████████████████████████████████               |  ETA: 0:00:34
Computing... 79%|███████████████████████████████████████           |  ETA: 0:00:24
Computing... 88%|████████████████████████████████████████████      |  ETA: 0:00:14
Computing... 97%|█████████████████████████████████████████████████ |  ETA: 0:00:03
Computing...100%|██████████████████████████████████████████████████| Time: 0:01:53

asyncmap

progressmeter.jl is awesome! works great for map, but sadly not asyncmap:

julia> using ProgressMeter
julia> prog = Progress(100)
julia> map(x->(sleep(1); next!(prog)),1:100)      ### works!
Progress:   3%|█                                        |  ETA: 0:02:43

julia> asyncmap(x->(sleep(1); next!(prog)),1:100; ntasks=1)    ### works!
Progress:   5%|██                                       |  ETA: 0:02:58

julia> asyncmap(x->(sleep(1); next!(prog)),1:100; ntasks=3)    ### no worky :(
Progress:   7%|███                                      |  ETA: 0:03:36Progress:   8%|███                                      |  ETA: 0:03:07Progress:   9%|████                                     | Progress:  10%|████                                     |  ETA: 0:02:36Progress:  11%|█████                                    |  ETA: 0:02:20Progress:  12%|█████                                    | Progress:  13%|█████                                    |  ETA: 0:02:02Progress:  14%|██████                                   |  ETA: 0:01:52Progress:  15%|██████

any idea why it would print multiple progress bars for the asyncmap with multiple tasks, but not for that with a single task, or with map? thanks.

UndefVarError

In Julia v1.0 I am getting this strange error message when I try to use ProgressMeter:

using Random
using ProgressMeter

seed = 0
@showprogress 1 "Simulating..." for i=1:10
    err = true
    while err
        Random.seed!(seed)
        seed += 1
        err = false
    end
end

seed

I was thinking this had to do with the new hard scoping rules, but the issue is really related to ProgressMeter.jl. If I remove the @showprogress annotation from the loop, the code works as expected. Could you please give some help?

Extra characters displayed in progress meter

Hello,
First, thank you for your excellent work with this package!

In my progress meter, a portion of the ANSI escape sequences are being displayed in the console. Such that they look like this:

[1GYear 1 simulation progress 31%|███████████████ | ETA: 0:17:47[K

I am using Juno, and I suspect this may be an issue with how Juno handles these sequences and not an issue with your package. Can you offer any insight? Thank you!

IJulia support

It would be nice if ProgressMeter would be able to detect and support IJulia.

Currently the output of ProgressMeter is just appended as continuous output

Allow to update the description

It would be nice, if ProgressMeter can support updating the description line during the task execution, e.g. to monitor the current minimal value during function optimization.

Errors when progress is zero

I get a regular callback with progress and sometimes that progress is zero causing an error:

julia> using ProgressMeter

julia> p = Progress(100, 1)
ProgressMeter.Progress(100, 1.0, 0, 1.512776740731284e9, 1.512776740731284e9, false, "Progress: ", 41, ProgressMeter.BarGlyphs('|', '█', '█', ' ', '|'), :green, Base.TTY(uRawFD(10) open, 0 bytes waiting), 0)

julia> update!(p, 0)
ERROR: InexactError()
Stacktrace:
 [1] trunc(::Type{Int64}, ::Float64) at ./float.jl:672
 [2] #updateProgress!#5(::Array{Any,1}, ::Symbol, ::Function, ::ProgressMeter.Progress) at /home/keno/.julia/v0.6/ProgressMeter/src/ProgressMeter.jl:156
 [3] #update!#9(::Array{Any,1}, ::Function, ::ProgressMeter.Progress, ::Int64) at /home/keno/.julia/v0.6/ProgressMeter/src/ProgressMeter.jl:231
 [4] update!(::ProgressMeter.Progress, ::Int64) at /home/keno/.julia/v0.6/ProgressMeter/src/ProgressMeter.jl:230

Cursor disappears after using `showvalues`

I was looking to add this to the README as an example for the showvalues functionality:

x,n = 1,10
p = Progress(n)
for iter = 1:10
    x *= 2
    sleep(0.5)
    ProgressMeter.next!(p; showvalues = [(:iter,iter), (:x,x)])
end

Upon doing this, I realized that my cursor in the REPL was gone!

screen shot 2016-08-10 at 12 06 21 am

For reference, this is what it looks like when I run the same loop, but don't use showvalues:

screen shot 2016-08-10 at 12 09 13 am

I believe I see this on both v0.5 and v0.4 -- I'm using the basic Terminal app on a Mac if that is important.

cc @robertfeldt

Line not overwritten when progress is at 100%

julia> using ProgressMeter

julia> p = Progress(100, 1)
ProgressMeter.Progress(100, 1.0, 0, 1.512777222765478e9, 1.512777222765478e9, false, "Progress: ", 41, ProgressMeter.BarGlyphs('|', '█', '█', ' ', '|'), :green, Base.TTY(RawFD(10) open, 0 bytes waiting), 0)

julia> for i = 1:100
       update!(p, 100)
       sleep(1)
       end
Progress: 100%|█████████████████████████████████████████| Time: 0:01:16
Progress: 100%|█████████████████████████████████████████| Time: 0:01:17
Progress: 100%|█████████████████████████████████████████| Time: 0:01:18
Progress: 100%|█████████████████████████████████████████| Time: 0:01:19
Progress: 100%|█████████████████████████████████████████| Time: 0:01:20

barspec, e.g. "[=> ]"

Hi all,

I have been extremely satisfied by all of the status bars crossing my screen since I discovered this package. However, sometimes the solid blocks just aren't what I'm looking for aesthetically. Would it be ok to allow customization of the characters in the progress bar?

The easiest way I can think of to do this is to add a keyword argument to the constructor called barspec that is a 5 character string. The first character is the left end, the second character is the bar fill character, the third character is the front end of the bar, the fourth character is the empty character, and the fifth character is the right end.

For example,
"[#> ]" would produce a bar like [########> ],
other examples could be "[=> ]", or "wot !" :)

Let me know if you think this is a good idea. I'll submit a PR in a few minutes.

Tests fail on nightly

0.5-style comprehensions changed loopassign.head to :generator in some cases, see http://pkg.julialang.org/detail/ProgressMeter.html

Testing @showprogress macro on for loop
...
[1GProgress:  37%  ETA: 0:00:09�[K�[1GProgress:  40%  ETA: 0:00:08�[K�[1GProgress:  43%  ETA: 0:00:07�[K�[1GProgress:  47%  ETA: 0:00:06�[K�[1GProgress: 100% Time: 0:00:05�[K
ERROR: LoadError: LoadError: AssertionError: loopassign.head === :(=)
 in include_from_node1(::String) at ./loading.jl:426 (repeats 2 times)
 in process_options(::Base.JLOptions) at ./client.jl:266
 in _start() at ./client.jl:322
while loading /home/vagrant/.julia/v0.5/ProgressMeter/test/test.jl, in expression starting on line 106

Just changing the assertion to be more permissive (VERSION for the 0.5-style comprehensions merge commit is v"0.5.0-dev+5297") doesn't seem to fix matters, so it might be a bit complicated to fix.

Progress Meter as a Plot?

A good addition to this package would be to add progress meters as plots, such as found in this MATLAB package. This allows for one to have multiple progress meters for long nested calculations, and could potentially skirt around printing/updating issues of some IDEs (example, currently the Juno/Atom IDE makes a new line for each step of the calculation).

The only problem is that Julia doesn't have a canonical plotter, so it's not clear which one should be used for this.

ProgressMeter missing in 0.4?

I liked ProgressMeter a lot in 0.3, but now that I've switched,

julia> Pkg.add("ProgressMeter.jl")
ERROR: unknown package ProgressMeter.jl
 in error at /Applications/Julia-0.4.0.app/Contents/Resources/julia/lib/julia/sys.dylib
 [inlined code] from pkg/entry.jl:49
 in anonymous at task.jl:447

I've Pkg.updated, and all of the other packages work fine (ProfileView, Images, Gadfly, etc.)

feature request: progress for unknown number of steps

Suppose I am reading an ex ante unknown number of records from a large file. It would be nice to do something like

prog = ProgressOnline("reading records")
while !eof(io)
    line = readline(io)
    ProgressMeter.update!(prog) # would just increment a counter, no second arg
    ... # process line
end
ProgressMeter.update!(prog, nothing) # done

while would display something like

reading records: 42000

Progress bar not displayed in Jupyter notebooks

Hi,

Print operations are sometimes delayed in Jupyter as if we needed to flush the buffer to STDOUT. This is happening with the progress bar in this package. Is there any way to force the display of the bar? What is happening that Jupyter doesn't print until the very end of the simulation?

segfault with @threads

Using ProgressMeter with the @threads functionality causes a segfault because the default print methods aren't thread safe. From what I can tell, using Core.print will solve the problem.

I can knock together a quick test soon if you like.

New release for 1.0

Hey @timholy, can you tag a new release for v1.0 please? Amazingly enough, there are 102 recursive dependencies on this package, so this humble package is high on our list of things to get working for 1.0. :)

Working with pmap

I thought I should note here that I found working with pmap and ProgressMeter a bit tricky, so I bundled the solution as a very simple package: https://github.com/slundberg/PmapProgressMeter.jl which provides pmap(p::Progress, f::Function, values).

This is related to #9 and it may be of interest to eventually merge this into ProgressMeter.

STDOUT by default?

Why does this package uses STDOUT by default? It can be very cumbersome to manually redirect every progress bar if one wants to pipe the output of a program to a file.

allow Progress(30.0,...) with a float?

julia> using ProgressMeter

julia> p = Progress(100.0,"my meter")
ERROR: MethodError: no method matching ProgressMeter.Progress(::Float64, ::String)

I expected this to work, as far as I can tell, it just divides the argument to update by that first argument to get a percentage. That works just as well with a Float as it does with an Integer.

I think restricting the dispatch on next! would be required.

Nested progress bars

Is it possible to produce nested progress bars as in a big task composed of smaller tasks?

Option for ProgressMeter to for short tasks

When the task takes less time than progressmeter.dt, the ProgressMeter is never printed. This is probably desirable in many cases, but I have cases where I would like it to print even if the task finishes quickly. For now I do progressmeter.tlast-=1 after creation, but thats a bit of a hack. Maybe a keyword argument print_immediately=true could be added?

ProgressMeter.next! prints as many bars as updates (on Jupyter notebook)

Hello,

When I use ``ProgressMeter.next!(progressbar; showvalues = [(:epoch, epoch), (:acc, acc)])`

I get the following behaviour

Progress:   5%|██                                       |  ETA: 0:00:13
  epoch:  1
Progress:  10%|████                                     |  ETA: 0:00:11
  epoch:  2
Progress:  15%|██████                                   |  ETA: 0:00:09
  epoch:  3
Progress:  20%|████████                                 |  ETA: 0:00:08
  epoch:  4

I was expecting a single bar that changed, not multiple of them.
I have tried with @showprogressand it works as expected. This is the output:

fit!(percep, X_train, y_train, 20, 0.001)
Progress: 100%|█████████████████████████████████████████| Time: 0:00:07

Use Base logging for progress meters

Base now has a way to log progress information. Juno is using:

@logmsg -1 "making progress" progress=0.5 # or progress=NaN, or progress="done"

This means that the standard logging setup can generate the logging information. It would be good if on v0.7 ProgressMeter.jl becomes simply a way of displaying this logging information. This way every package can natively support progress meters and how it is displayed just becomes a user-preference or IDE side issue.

This should be done in coordination with @pfitzseb and his work on Juno.

Different ProgressBar styles?

I was wondering if this can be done. I created a small repo in Julia, which gives different styles of Spinners which can show progress on the CLI.

Code here, Spinner.jl

Supporting `map` and friends

I don't have any experience writing macros yet, but is it possible to let @showprogress support functions like map (and foreach, which has recently been added to Julia master)? I guess you could rewrite

@showprogress map(f, itr)

as something like

p = Progress(length(itr))
map(x -> (next!(p); f(x)), itr)

although I don't know if you need extra precautions in case itr doesn't have a length defined for whatever reason.

Allow update also of (status) values

Thanks for ProgressMeter; very useful. For long-running computations (such as for example in optimization) it would be nice to allow a dict (or some other way) to specify current values which can then be reported on the lines below the progress bar? For example, in the optimiation, when want to know the overall progress in terms of time (ETA) but also would like to know the objective value of the current best solution found. If these are just printed to STDOUT it would mess up the reporting from ProgressMeter so it seems there needs to be some support for this. Has this been considered as a future extension? If not, if this is something you could accept as a PR I might take a stab at it.

feature-request: pmap with keyword arguments

The following currently doesn't work:

using Distributed
addprocs()
@everywhere using ProgressMeter
xs = range(0,stop=1,length=200)
@everywhere f = x -> x+1
@showprogress pmap(f,xs; batch_size=10)

I get the error ERROR: syntax: unexpected semicolon in tuple. It would be really cool if ProgressMeter could deal with the batch_size keyword argument correctly, as for a lot of distributed applications where one would want a progress bar as there are so many items to pmap over, it doesn't make sense to have batch_size==1

Bug in Atom.io

Progress meter in Atom.io looks like this
�[1Gtest... 20%|████ | ETA: 0:00:04�[K

adding one more condition to printover function fixed it


function printover(io::IO, s::AbstractString, color::Symbol = :color_normal)
    if isdefined(Main, :IJulia) || isdefined(Main, :ESS) || isdefined(Main, :Atom)
        print(io, "\r" * s)
    else
       ......

Thread-safety of ProgressMeter

Hi Tim! Me again =)

Is there something special I need to do to use ProgressMeter for parallel computations? I tried something like

function long_running_function()
    n = 100
    p = Progress(n, 1)
    @parallel for i in 1:n
        sleep(0.1)
        next!(p)
    end
end

addprocs(3)

@everywhere using ProgressMeter

long_running_function()

but the call just returned and nothing was printed. I guess it's because p is only defined locally, but I haven't done enough parallel programming in Julia to see intuitively how to make it work on all processes. Adding some @spawn and @fetch calls has some, but not all of the desired, effect - it does print the progress line, but only at the very end, at the same time as the REPL prints the return value.

function long_running_function2()
    n = 100
    p = @spawn Progress(n, 1)
    @parallel for i in 1:n
        sleep(0.1)
        next!(fetch(p))
    end
end

showvalues option does not work in IJulia

using ProgressMeter

p = Progress(100)

for i=1:100
    sleep(1)
    next!(p, showvalues=[(:i,i)])
end

It keeps adding lines vertically instead of overwriting the existing line.

progress to file?

Is it possible to set progress meter to update a text file for nohup scripts? Easy to do by hand, but thought it might be convenient to just add a filename to the argument to have it save the output.

Great tool!

Jon

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.