gpt4 book ai didi

python - 在进度条的计算中实现python多线程

转载 作者:行者123 更新时间:2023-12-03 13:23:00 25 4
gpt4 key购买 nike

我正在尝试创建类似于tqdm的进度条。一切正常,但我注意到进度条每一步的计算(对于大型可迭代对象,len> 50)都需要花费大量时间。这是我的代码。

def progressbar(iterable):
def new(index):
#... print the progressbar
for i in range(len(iterable)):
new(i)
yield iterable[i]
问题是,虽然在小的可迭代项上 new()执行的时间是无关紧要的,但是在较大的可迭代项上,这成为一个问题(在tqdm库中不会发生)。例如,以下代码需要花费几秒钟的时间才能执行。应该是即时的!
iterator = progressbar(range(1000))
for i in iterator: pass
你能告诉我补救办法吗?也许实现多线程?

最佳答案

目前尚不清楚是什么问题(您不会显示所有计算结果),但是我相信您可以通过进度栏处理正在传递的iterable的方式来改进您的方法:

  • 首先,您假设iterable是可索引的,但情​​况并非总是如此。
  • 如果它是一个生成器函数,则长度可能无法通过len函数确定,也无法将生成器转换为列表以获取其长度必定是有效的,并且可能无法达到使用进度条的目的,例如下面的例子。因此,您的界面应允许用户传递可选的total参数(就像tqdm一样)以显式指定iterable的长度。
  • 您可以在函数new之外进行一些前期计算,以便new可以根据index参数的值快速计算小节的宽度。

  • 我建议进行以下更改:
    def progressbar(iterable, total=None):
    def new(index):
    #... print the progressbar
    from math import floor
    nonlocal division, width
    n_division = floor(index / division + .5)
    remainder = width - n_division
    print('|', '.' * n_division, ' ' * remainder, '|', sep='', end='\r')

    if total is None:
    iterable = list(iterable)
    # we must convert to a list
    total = len(iterable)
    it = iter(iterable)

    width = 60 # with of progress bar
    division = total / 60 # each division represents this many completions

    try:
    for i in range(total):
    # ensure next value exists before printing it:
    yield next(it)
    new(i)
    except StopIteration:
    pass
    print()

    def fun():
    import time
    for i in range(1000):
    time.sleep(.03)
    yield i

    iterator = progressbar(fun(), total=1000)
    values = [i for i in iterator]
    print(values[0], values[-1])
    多线程
    将多线程作为一种加速处理的方式是有问题的。以下是一次(幼稚的)尝试,但失败了,因为尽管使用了多线程从生成器函数 fun获取值,但是生成器函数仍仅每.03秒生成一次值。还应该清楚,例如,如果 iterable是一个简单列表,那么多线程将比使用单个线程更快地迭代该列表:
    from multiprocessing.pool import ThreadPool


    def progressbar(iterable, total=None):
    def new(index):
    #... print the progressbar
    from math import floor
    nonlocal division, width
    n_division = floor(index / division + .5)
    remainder = width - n_division
    print('|', '.' * n_division, ' ' * remainder, '|', sep='', end='\r')
    if total is None:
    iterable = list(iterable)
    # we must convert to a list
    total = len(iterable)
    it = iter(iterable)

    width = 60 # with of progress bar
    division = total / 60 # each division represents this many completions

    with ThreadPool(20) as pool:
    for i, result in enumerate(pool.imap(lambda x: x, iterable)):
    yield result
    new(i)
    print()

    def fun():
    import time
    for i in range(1000):
    time.sleep(.03)
    yield i

    iterator = progressbar(fun(), total=1000)
    values = [i for i in iterator]
    print(values[0], values[-1])
    如果生成器函数本身使用了多线程,将会加速处理。但是,当然,无法控制 iterable的创建方式:
    from multiprocessing.pool import ThreadPool


    def progressbar(iterable, total=None):
    def new(index):
    #... print the progressbar
    from math import floor
    nonlocal division, width
    n_division = floor(index / division + .5)
    remainder = width - n_division
    print('|', '.' * n_division, ' ' * remainder, '|', sep='', end='\r')

    if total is None:
    iterable = list(iterable)
    # we must convert to a list
    total = len(iterable)
    it = iter(iterable)

    width = 60 # with of progress bar
    division = total / 60 # each division represents this many completions

    try:
    for i in range(total):
    # ensure next value exists before printing it:
    yield next(it)
    new(i)
    except StopIteration:
    pass
    print()


    def fun():
    import time

    def fun2(i):
    time.sleep(.03)
    return i

    with ThreadPool(20) as pool:
    for i in pool.imap(fun2, range(1000)):
    yield i

    iterator = progressbar(fun(), total=1000)
    values = [i for i in iterator]
    print(values[0], values[-1])

    关于python - 在进度条的计算中实现python多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64879682/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com