【问题标题】:Using tqdm progress bar in a while loop在 while 循环中使用 tqdm 进度条
【发布时间】:2018-01-30 04:18:42
【问题描述】:

我正在编写一个代码来模拟一个棋子在垄断板上转一百万次。 我想要一个 tqdm 进度条,每次完成转板时都会更新。

下面是我当前的代码。我正在使用一个 while 循环,当电路板的转数超过所需数量时,它会停止。

import os
from openpyxl import Workbook
from monopolyfct import *


def main(runs, fileOutput):

    ### EXCEL SETUP ###
    theWorkbook = Workbook()                              # Creates the workbook interface.
    defaultSheet = theWorkbook.active                     # Creates the used worksheet.
    currentData = ["Current Table Turn", "Current Tile"]  # Makes EXCEL column titles.
    defaultSheet.append(currentData)                      # Appends column titles.

    ### CONTENT SETUP ###
    currentData = [1, 0]             # Sets starting position.
    defaultSheet.append(currentData) # Appends starting position.

    while currentData[0] <= runs:

        ### ROLLING THE DICES PROCESS ###
        dices = twinDiceRoll()
        currentData[1] += dices[2]  # Updating the current tile

        ### SURPASSING THE NUMBER OF TILES ONBOARD ###
        if currentData[1] > 37:   # If more than a table turn is achieved,
            currentData[0] += 1   # One more turn is registered
            currentData[1] -= 38  # Update the tile to one coresponding to a board tile.
        else:
            pass

        ### APPENDING AQUIRED DATA ###
        defaultSheet.append(currentData)

        ### MANAGIING SPECIAL TILES ###
        if currentData[1] == 2 or 15 or 31:   # Community chess
            pass                              #TODO: Make a mechanic simulating the community chest card draw and it's related action.
        elif currentData[1] == 5 or 20 or 34: # Chance
            pass                              #TODO: Make a mechanic simulating the chance card draw and it's related action.
        elif currentData[1] == 28:            # Go to Jail
            pass                              #TODO: Make a mechanic simulating the entire jail process

        ### TWIN DICE ROLL EXCEPTION ###
        if dices[3] is True:  # If the dices roll a double,
            pass              #TODO: Make a mechanic considering that three doubles sends one to Jail.


    ### STORING THE ACCUMULATED DATA ###
    theWorkbook.save(fileOutput)  # Compiles the data in a .xlxs file.


if __name__ == "__main__":
    terminalWidth = os.get_terminal_size().columns                                               # Gets current terminal width.
    space(3)
    print("Python Monopoly Statistics Renderer".upper().center(terminalWidth))                   # Prints the title.
    print("(PMSR)".center(terminalWidth))                                                        # Prints the acronym.
    space(2)
    runs = int(request("For how many table turns do you want the simulation to run?"))           # Prompts for the desired run ammount
    #runs = 1000
    fileOutput = request("What should be the name of the file in which statistics are stored?")  # Prompts for the desired store filename
    #fileOutput = "test"
    fileOutput += ".xlsx"                                                                        # Adds file extension to filename
    main(runs, fileOutput)

【问题讨论】:

  • 如果你提前知道runs 的值,为什么不直接使用for循环呢?

标签: python python-3.x tqdm


【解决方案1】:

您可以通过在构造函数中指定total 参数来在tqdm 中使用手动控制。逐字逐句来自manual

with tqdm(total=100) as pbar:
    for i in range(10):
        sleep(0.1)
        pbar.update(10)

更新

要在没有上下文管理器的情况下手动控制tqdm(又名with 语句),您需要在完成使用后关闭进度条。这是手册中的另一个示例:

pbar = tqdm(total=100)
for i in range(10):
    sleep(0.1)
    pbar.update(10)
pbar.close()

为此,您需要知道预期运行的总数。在您的代码中,它可能看起来像

...
pbar = tqdm(total = runs+1)
while currentData[0] <= runs:

    ### ROLLING THE DICES PROCESS ###
    dices = twinDiceRoll()
    currentData[1] += dices[2]  # Updating the current tile

    ### SURPASSING THE NUMBER OF TILES ONBOARD ###
    if currentData[1] > 37:   # If more than a table turn is achieved,
        currentData[0] += 1   # One more turn is registered
        currentData[1] -= 38  # Update the tile to one coresponding to a board tile.
        pbar.update(1)
    else:
        pass
...
pbar.close()

但是,这段代码并不完美:考虑一下currentData[1] 是否总是小于 37 —— 进度条只会停止而不更新。如果您尝试在else:... 部分中更新它,您可能会违反total 上限。这是一个开始:)

【讨论】:

  • 要使上述代码正常工作,您需要from tqdm import tqdmpbar = tqdm.tqdm(total=100)
  • 更好的做法,使用with tqdm(total=100) as pbar: do... ; pbar.update(10)
  • 非常有用,谢谢!
【解决方案2】:

由于受到关注,这篇文章很吸引我,我认为最好指出如何通过无限循环来实现这一点。

要在 tqdm 中使用无限循环,您需要使用生成器将 while 循环更改为无限 for 循环。

无限循环(无进度条)

while True:
  # Do stuff here

无限循环(带进度条)

def generator():
  while True:
    yield

for _ in tqdm(generator()):
  # Do stuff here

上面的代码会创建一个类似这样的不定进度条

16it [01:38,  6.18s/it]

请注意,也可以修改生成器以使用条件

def generator():
  while condition:
    yield

【讨论】:

  • 确实是很好的解决方案。
猜你喜欢
  • 1970-01-01
  • 2018-10-12
  • 2018-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-10
  • 2021-02-19
相关资源
最近更新 更多