I've been working on a simple GUI within Python to pull data from PowerBi, that looks similar to the image below:
The app works fine, however I am looking to improve it's efficiency.
The checkbar is produced with the following code:
Datasets = [
'Option 1', 'Option 2', 'Option 3',
'Option 4', 'Option 5',
'Option 6', 'Option 7',
'Option 8', 'Option 9']
print(os.getcwd())
cwd = os.getcwd
class Checkbar(Frame):
def __init__(self, parent=None, picks=[], side=LEFT, anchor=W):
Frame.__init__(self, parent)
self.vars = []
for pick in picks:
var = IntVar()
chk = Checkbutton(self, text=pick, variable=var, width=22, anchor='w')
chk.pack(side=side, anchor=anchor, expand=YES)
self.vars.append(var)
def state(self):
return map((lambda var: var.get()), self.vars)
if __name__ == '__main__':
root = Tk()
root.title("PowerBI Data Collector")
root.iconphoto(True, PhotoImage(
file="Icon/Directory"))
responseLabel = Label(root)
# Check
data1 = Checkbar(root, Datasets[0:3], anchor=W)
data2 = Checkbar(root, Datasets[3:6], anchor=W)
data3 = Checkbar(root, Datasets[6:9], anchor=W)
data1.grid(row = 3, column = 1, padx = 1, pady = 1)
data1.config(relief=GROOVE, bd=1)
data2.grid(row = 4, column = 1, padx = 1, pady = 1)
data2.config(relief=GROOVE, bd=1)
data3.grid(row = 5, column = 1, padx = 1, pady = 1)
data3.config(relief=GROOVE, bd=1)
Based on the user's choice's from the checkbars, a list of 0's and 1's is produced describing the state of the input, using the code:
dataState = list(data1.state())
dataState.extend(list(data2.state()))
dataState.extend(list(data3.state()))
As such, if option 2 and option 4 is chosen, the dataState will read: [0,1,0,1,0,0,0,0,0]
From here there are a number of if
statements that check for whether their respective integers from the list is a 1, and if so calls the respective function to pull the data specific to that checkbox from PowerBi. A few of which are detailed below:
if dataState == [0]*len(Datasets): # nothing
responseLabel.destroy()
responseLabel = Label(text = "Please select from the checklist above")
responseLabel.grid(row = 7, column = 1)
if dataState[0] == 1: # option2
# Response Label
responseLabel.destroy()
try:
uf.option2(User=userDetails[0], Pass = userDetails[1])
responseLabel = Label(text = "All data downloaded")
responseLabel.grid(row = 7, column = 1)
except:
responseLabel = Label(text = "option 1 data download failed")
responseLabel.grid(row = 7, column = 1)
if dataState[1] == 1: # option1
# Response Label
responseLabel.destroy()
try:
uf.option1(User=userDetails[0], Pass = userDetails[1])
responseLabel = Label(text = "All data downloaded")
responseLabel.grid(row = 7, column = 1)
except:
responseLabel = Label(text = "option 2 data download failed")
responseLabel.grid(row = 7, column = 1)
This is quite inefficient and was fine when there were only 3 options, but now there are 9, and more are expected to be added. I was thinking of converting the if
statement section to a for
loop, and the iteration of the loop that corresponded to a 1 within the list called a specific function, but this too seemed inefficient so I pose the question here, with the hopes of finding a better suggestion.
Thanks!
A simple, scalable option would be to make each option's code into a function and put them into a list
or tuple
, e.g.:
optionFunc = (opt1, opt2, opt3, etc.)
Then you could iterate through dataState
and call the associated function, something like:
for index, state in enumerate(dataState):
if state:
option_func[index](responseLabel)
There may be a more sophisticated way to do this, maybe the GUI code you're using can associate labels with the checkboxes that you can use as dictionary indexes, but this would be the general idea.
(I put optionFunc
in camelCase
to be consistent with the rest of your code, but in Python snake_case
would be the preferred form)