在 while 循环中使用 tqdm 进度条

我正在编写一个代码,模拟一个小卒在垄断董事会周围转了一百万次。 我想有一个 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)
118711 次浏览

You can use manual control in tqdm by specifying a total argument in the constructor. Verbatim from the manual:

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

UPDATE

To manually control the tqdm without the context manager (aka with statement), you will need to close the progress bar after you are done using it. Here is another example from the manual:

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

For this to work you need to know the total number of expected runs. In your code it could look something like

...
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()

However, this code isn't perfect: consider if the currentData[1] is always less than 37 -- the progress bar will just stop and not update. If you try to update it in the else:... part, you might violate the total upper bound. This is a start tho :)

Because of the attention, this post is attracting I thought it would be good to point out how this can be achieved with an infinite while loop as well.

To use an infinite loop with tqdm you need to change your while loop into an infinite for loop by utilizing a generator.

Infinite loop (no progress bar)

while True:
# Do stuff here

Infinite loop (with progress bar)

def generator():
while True:
yield


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

The code above would create an indefinite progress bar that would look similar to this

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

Note that the generator could also be modified to work with a condition

def generator():
while condition:
yield

An additional version for user12128336's answer.

You can do all iteration stuff inside a generator. Just add yield at the end of iteration.

from tqdm.auto import tqdm
from time import sleep




def generator():
while True:
sleep(0.3) # iteration stuff
yield
        

for _ in tqdm(generator()): pass


# 77it [00:23,  3.25it/s]