卓越飞翔博客卓越飞翔博客

卓越飞翔 - 您值得收藏的技术分享站
技术文章34114本站已运行391

如何用mpb创建两行进度条?

如何用mpb创建两行进度条?

问题内容

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

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

list := []string{"c:temp01.png",  "c:temp02.png",  "c:temp03.png",  "c:temptest.png",  "c:temptest01.png"}

我希望它像这样显示:

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

等等。

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

  1. 我想显示有关当前处理状态的附加信息。
    processing 01.png ... [mode: webp]
    0 / 5 [                    ] 0%
  2. 有时,我必须处理同一个文件两次。
    processing 01.mp4 ... [mode: webm] [pass: 1/2]
    0 / 5 [                    ] 0%
    processing 01.mp4 ... [mode: webm] [pass: 2/2]
    0 / 5 [                    ] 0%
    请注意,进度条未更改。
  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%
    当事情发生变化时,每个进度条都应该尽快更新,而不是“每 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
    })
}

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

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

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),
        ),
    )

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

在这个示例中,为了演示如何制作新栏,我使用了 new() 方法,但经过一些研究后,我发现还有更多方法可以制作新栏。区别主要在于酒吧的外观。您可以通过在 progress 结构的方法列表中查找返回 bar 实例的方法来找到它们nofollow noreferrer">文档。

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

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

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

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

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

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

在此示例中,每个装饰都会根据其循环中的设置值增加 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()
    }

这个循环也适用于第二个小节。我只是将两个条形的增量状态组合在一个循环中以使代码更短。如果循环变量小于 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  
[===>--------------------------------------------------------------------------]
file.extension percentage: 49% part 2/5 pass 0/2  
[=====================================>----------------------------------------]
file2.extension percentage: 24% part 2/10 pass 0/4  
[==================>-----------------------------------------------------------]
file.extension percentage: 100% part 5/5 pass 2/2  
[==============================================================================]
file2.extension percentage: 74% part 7/10 pass 2/4  
[=========================================================>--------------------]
file.extension Percentage: 100% Part 5/5 Pass 2/2  
[==============================================================================]
file2.extension Percentage: 100% Part 10/10 Pass 4/4  
[==============================================================================]
卓越飞翔博客
上一篇: docker compose healthcheck 未退出并出现错误无法启动
下一篇: 返回列表
留言与评论(共有 0 条评论)
   
验证码:
隐藏边栏