Benjamin Chausse Benjamin Chausse - 1 month ago 35
Python Question

Using tqdm progress bar in a while loop

I am making a code that simulates a pawn going around a monopoly board a million times.
I would like to have a tqdm progress bar that is updated every time a turn around the board is achieved.

Below is my current code. I am using a while loop which stops when the number of turns around the board surpasses the desired number.

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)

Answer Source

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

pbar = tqdm(total=100)
for i in range(10):
    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 :)