Home > Backend Development > Golang > How to create a two-line progress bar with mpb?

How to create a two-line progress bar with mpb?

WBOY
Release: 2024-02-06 08:51:08
forward
855 people have browsed it

How to create a two-line progress bar with mpb?

问题内容

我正在尝试用 mpb 制作两行进度条。

假设我有一个包含文件绝对路径的切片。

list := []string{"c:\temp\01.png",  "c:\temp\02.png",  "c:\temp\03.png",  "c:\temp\test.png",  "c:\temp\test01.png"}
Copy after login

我希望它像这样显示:

processing 01.png ...
0 / 5 [                    ] 0%
Copy after login
processing 02.png ...
1 / 5 [==                  ] 20%
Copy after login
processing 03.png ...
2 / 5 [====                ] 40%
Copy after login

等等。

将“正在处理...”部分和进度条分开的原因是:

  1. 我想显示有关当前处理状态的附加信息。
    processing 01.png ... [mode: webp]
    0 / 5 [                    ] 0%
    Copy after login
  2. 有时,我必须处理同一个文件两次。
    processing 01.mp4 ... [mode: webm] [pass: 1/2]
    0 / 5 [                    ] 0%
    Copy after login
    processing 01.mp4 ... [mode: webm] [pass: 2/2]
    0 / 5 [                    ] 0%
    Copy after login
    请注意,进度条未更改。
  3. 我也想一次制作多个进度条。
    Processing 01.mp4 ... [Mode: WebM] [Pass: 1/2]
    4 / 5 [================    ] 0%
    Processing 01.png ... [Mode: WebP]
    2 / 5 [========            ] 0%
    Processing DONE [Mode: MP3]
    5 / 5 [====================] 100%
    Copy after login
    当事情发生变化时,每个进度条都应该尽快更新,而不是“每 0.5 秒更新每个进度条”。

我找不到这样做的方法。 mpb 的每个示例代码都是在单行中完成其工作。


正确答案


我第一次看到这个库,但在探索了一些代码之后,我发现了如何根据我们的需要添加新的和自定义的栏。我对您在评论中提供的链接示例进行了一些修改,以演示添加和自定义栏。

package main

import (
    "fmt"
    "io"
    "math/rand"
    "time"

    "github.com/vbauerster/mpb/v8"
    "github.com/vbauerster/mpb/v8/decor"
)

func main() {
    p := mpb.new()

    var piece, piece2 int64

    var way, way2 int64

    file := func(_ decor.statistics) string {

        return "file.extension "
    }

    file2 := func(_ decor.statistics) string {

        return "file2.extension "
    }

    part := func(s decor.statistics) string {

        s.current = piece
        s.total = 5
        return fmt.sprintf(" part %d/%d", s.current, s.total)
    }

    part2 := func(s decor.statistics) string {

        s.current = piece2
        s.total = 10
        return fmt.sprintf(" part %d/%d", s.current, s.total)
    }

    pass := func(s decor.statistics) string {

        s.current = way
        s.total = 2
        return fmt.sprintf(" pass %d/%d", s.current, s.total)
    }

    pass2 := func(s decor.statistics) string {

        s.current = way2
        s.total = 4
        return fmt.sprintf(" pass %d/%d", s.current, s.total)
    }
    var total = 100

    bar := p.new(int64(total),
        mpb.nopstyle(), // make main bar style nop, so there are just decorators
        mpb.barextender(extended(mpb.barstyle().build()), false), // extend wtih normal bar on the next line
        mpb.prependdecorators(
            decor.any(file),
            decor.name("percentage: "),
            decor.newpercentage("%d"),
            decor.any(part),
            decor.any(pass),
        ),
    )

    bar2 := p.new(int64(total+100),
        mpb.nopstyle(),
        mpb.barextender(extended(mpb.barstyle().build()), false),

        mpb.prependdecorators(
            decor.any(file2),
            decor.name("percentage: "),
            decor.newpercentage("%d"),
            decor.any(part2),
            decor.any(pass2),
        ),
    )
    // simulating some work
    max := 100 * time.millisecond

    for i := 0; i < total+100; i++ {

        switch {
        case i == 20 || i == 40 || i == 60 ||
            i == 80 || i == 100 || i == 120 ||
            i == 140 || i == 160 || i == 180:
            piece2++

            if i == 100 {
                way2++

                piece = 5
                way = 2
            } else if i < 100 {
                piece++
            }

        case i == 50 || i == 150:

            if i < 100 {
                way++
            }

            way2++
        }

        time.sleep(time.duration(rand.intn(10)+1) * max / 10)

        if i < 100 {
            bar.increment()
        }
        bar2.increment()
    }

    way2 = 4
    piece2 = 10
    // wait for our bar to complete and flush
    p.wait()
}

func extended(base mpb.barfiller) mpb.barfiller {
    return mpb.barfillerfunc(func(w io.writer, st decor.statistics) error {
        err := base.fill(w, st)
        if err != nil {
            return err
        }
        _, err = io.writestring(w, "\n")
        return err
    })
}
Copy after login

假设您已经知道如何制作自定义装饰器。

要创建一个新栏,您可以执行以下操作:

bar := p.new(int64(total),
        mpb.nopstyle(), // make main bar style nop, so there are just decorators
        mpb.barextender(extended(mpb.barstyle().build()), false), // extend wtih normal bar on the next line
        mpb.prependdecorators(
            decor.any(file),
            decor.name("percentage: "),
            decor.newpercentage("%d"),
            decor.any(part),
            decor.any(pass),
        ),
    )
Copy after login

例如,我只制作了两个金条,但您制作了两个以上。

在这个示例中,为了演示如何制作新栏,我使用了 new() 方法,但经过一些研究后,我发现还有更多方法可以制作新栏。区别主要在于酒吧的外观。您可以通过在 文档

p.new() 的第一个参数用于定义条形的总值,在该条形中为 100。

只需将您的装饰器/部分放入 mpb.prependdecoratorsmpb.appenddecorators 即可。

mpb.prependdecorators(
            decor.any(file),
            decor.name("percentage: "),
            decor.newpercentage("%d"),
            decor.any(part),
            decor.any(pass),
        ),
Copy after login

您可以为每个栏使用相同的装饰器,但我建议为每个栏创建新的装饰器以避免发生冲突的可能性。

这将分别显示文件名、百分比、部分和通过:

file.extension percentage: 100% part 5/5 pass 2/2  
[==============================================================================]
Copy after login

在此示例中,每个装饰都会根据其循环中的设置值增加 1,循环遍历条形的总值。在这个栏中,我只是迭代了 1 到 100。我的目标是 100 到 5 个部分。当循环变量遇到100中的5个部分之一时,条形的part装饰会增加1。
而当达到50时,pass装饰就会增加1。

for i := 0; i < total+100; i++ {

        switch {
        case i == 20 || i == 40 || i == 60 ||
            i == 80 || i == 100 || i == 120 ||
            i == 140 || i == 160 || i == 180:
            piece2++

            if i == 100 {
                way2++

                piece = 5
                way = 2
            } else if i < 100 {
                piece++
            }

        case i == 50 || i == 150:

            if i < 100 {
                way++
            }

            way2++
        }

        time.sleep(time.duration(rand.intn(10)+1) * max / 10)

        if i < 100 {
            bar.increment()
        }
        bar2.increment()
    }
Copy after login

这个循环也适用于第二个小节。我只是将两个条形的增量状态组合在一个循环中以使代码更短。如果循环变量小于 100,则增加第一个柱的状态。当它达到100时,将所有装饰全部增加到总数,然后继续增加第二个栏的状态,直到循环结束。循环完成后,完成第二个条形增量的其余部分以达到总计。

65bd2e1fcfff

第二个栏包含 10 个零件和 4 个通道,总价值为 200。

整个代码的输出是:

file.extension percentage: 9% part 0/5 pass 0/2  
[======>-----------------------------------------------------------------------]
file2.extension percentage: 4% part 0/10 pass 0/4  
[===>--------------------------------------------------------------------------]
Copy after login
file.extension percentage: 49% part 2/5 pass 0/2  
[=====================================>----------------------------------------]
file2.extension percentage: 24% part 2/10 pass 0/4  
[==================>-----------------------------------------------------------]
Copy after login
file.extension percentage: 100% part 5/5 pass 2/2  
[==============================================================================]
file2.extension percentage: 74% part 7/10 pass 2/4  
[=========================================================>--------------------]
Copy after login
file.extension Percentage: 100% Part 5/5 Pass 2/2  
[==============================================================================]
file2.extension Percentage: 100% Part 10/10 Pass 4/4  
[==============================================================================]
Copy after login

The above is the detailed content of How to create a two-line progress bar with mpb?. For more information, please follow other related articles on the PHP Chinese website!

source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template