global variable not recognized; says its local variable [duplicate] - python

This question already has answers here:
UnboundLocalError trying to use a variable (supposed to be global) that is (re)assigned (even after first use)
(14 answers)
Closed 29 days ago.
Its not recognizing the global variable. I experienced this issue before and thought the global variable would prevent the error but no matter what i try it always returns this: local variable 'P1o' referenced before assignment
#import pwinput
import PySimpleGUI as sg
P1o = ("")
P2o = ("")
MAX_ROWS = MAX_COL = 10
def Battleship1():
layout = [
[sg.Text('Player1 please enter your ship positions'), sg.InputText('', size=(10,1), key='input_\P1o')],
[sg.Submit(), sg.Cancel()]
]
window = sg.Window('player1 values', layout)
while True:
event, values = window.read()
if event == sg.WIN_CLOSED:
break
elif event == 'Submit':
P1o = P1o.append(int(values['input_\P1o']))
window.close()
elif event == 'cancel':
window.close()
break
layout = [
[sg.Text('Player2 please enter your ship positions'), sg.InputText('', size=(10,1), key='input_\P2o')],
[sg.Submit(), sg.Cancel()]
]
window = sg.Window('player2 values', layout)
while True:
event, values = window.read()
if event == sg.WIN_CLOSED:
break
if event == 'Submit':
P1o = P1o.append(int(values['input_\P1o']))
turn()
turn_()
if event == 'cancel':
window.close()
break
""" i set up the multiplayer function"""
layout = [ [sg.Text("Welcome to battleship!!\nObject of the game is to sink all five of your enemy's ships!!!\nlabel your ship positions with a number (0-9)\n and another number (0-9)\n and separate each position with spaces e.g 1,2 2,3 3,4")],
[sg.Button('Single Player'), sg.Button('Multiplayer')] ]
window = sg.Window('Menu', layout)
while True:
event, values = window.read()
if event == sg.WIN_CLOSED:
break
if event == 'Multiplayer':
window.close()
Battleship1()
break

I would suggest you to use P1o and P2o as your local variables, as they are only needed in your battleship function.
You can use them as your global or as your local variables. I'll leave the choice to you.
CASE 1: Using it as local variable:
def Battleship1():
P1o = ""
P2o = ""
Here, it just creates two local variables for the function and would prevent the referenced before assignment error.
CASE 2: Using it as global variable:
def Battleship1():
global P1o, P2o
global keyword is used to reference the globals() dictionary where all the global variables are mentioned. So, it would tell the function that P1o and P2o is a global variable.

Related

PySimpleGUI update filepath only when new path is chosen

I made a GUI with PySimpleGUI where the user has the option to change the standard paths, which will be used in the program. I first defined my standard paths as strings, and then later the user can change them with the help of sg.IN and sg.FolderBrowse fields.
Here the Code:
stdPath1 = "PathToFolder1"
stdPath2 = "PathToFolder2"
layout =
[
[
sg.Text("optional new Path for Folder1:", size=(30, 1)),
sg.In(size=(25, 1), enable_events=True, key='-Folder1-'),
sg.FolderBrowse(),
],
[
sg.Text("optional new Path for Folder2:", size=(30, 1)),
sg.In(size=(25, 1), enable_events=True, key="-Folder2-"),
sg.FolderBrowse()
],
[sg.Button("Start")],
]
window = sg.Window("PrgmName", layout)
while True:
event, values = window.read()
if event == sg.WIN_CLOSED or event == "Exit":
break
elif event == "Start":
# start Program
elif event == "-Folder1-":
stdPath1 = values[event]+"/"
elif event == "-Folder2-":
stdPath2 = values[event]+"/"
window.close()
This works fine, however sometimes my program returns NONE.
I think this happens when the user clicks the button to choose a new path but closes the Browse window without selecting a new path. Then the event is also triggered, which results in a NONE value being given to my path variable. This of course leads to problems later in the program.
Therefore I would like to only update the FolderPath when a path is actually chosen, not when the button is clicked, but I don't know how to do this.
My only idea would be to add something like "if values[event] is not NONE then pass the new path, otherwise continue to use the stdpath". Is there a better way to do this?

Why am I getting "UnboundLocalError local variable 'coffee_machine' referenced before assignment" despite coffee_machine being a global variable? [duplicate]

This question already has answers here:
Using global variables in a function
(25 answers)
Closed 12 months ago.
coffee_machine = True
def user_input():
while coffee_machine:
user_choice = input("What type of coffee would you like espresso/latte/cappuccino?")
if user_choice == "off".lower():
coffee_machine = False
x = []
for ingredients in MENU[user_choice].get("ingredients").values():
x.append(ingredients)
print(x)
user_input()
You have not declared global coffee_machine at the start of the function, and thus it's not forced to be global, and within the function you try setting a value to it, which makes it local.
All that's needed to be done is adding that global line which will force it to be global, like so:
coffee_machine = True
def user_input():
global coffee_machine
while coffee_machine:
user_choice = input("What type of coffee would you like espresso/latte/cappuccino?")
if user_choice == "off".lower():
coffee_machine = False
x = []
for ingredients in MENU[user_choice].get("ingredients").values():
x.append(ingredients)
print(x)
user_input()

PySimpleGui can not access list in InputCombo

I am making a simple gui for my python script with PySimpleGui and enterd a problem. Everytime i want to add a new integer to my InputCombo list, I can not access the new integer.
I wrote a basic script to show:
import PySimpleGUI as sg
things=["a","b"]
layout=[[sg.Input(key="-input-",size=(10,1)),sg.Button("add",key="-add-")],
[sg.InputCombo(things,key="-combo-"),sg.Button("write")],
[sg.Text("",key="-output-"),sg.Button("Quit")]]
window=sg.Window("Name",layout,size=(200,200))
while True:
event,values=window.read()
if event==sg.WINDOW_CLOSED or event=="Quit":
break
if event=="add":
things.append(values["-input"])
if event=="write":
window["-output-"].update(values["-combo-"])
I have a list "things". I can add a new value, if I write something in the inputfield. WIth the Button "add" i add the value to my list "things". With the InputCombo I can access the vvalues in my list, for example "a" and "b". If I choose "a" or "b" an press "write", the Textfield will update and write "a" or "b". But in the InputCombo I can n ot choose values, which I have added later.
Does anybody have an idea how I can get things working?
Call method update(values=things) of sg.InputCombo to update new values.
Revised code,
import PySimpleGUI as sg
things = ["a","b"]
layout = [
[sg.Input(key="-input-", size=(10,1)),
sg.Button("add", key="-add-")],
[sg.InputCombo(things, key="-combo-"),
sg.Button("write")],
[sg.Text("", key="-output-"),
sg.Button("Quit")],
]
window = sg.Window("Name", layout, size=(200, 200))
while True:
event, values = window.read()
if event == sg.WINDOW_CLOSED or event == "Quit":
break
elif event == "-add-": # Correct event to add
things.append(values["-input-"])
window['-combo-'].update(values=things) # Statement to update
elif event == "write":
window["-output-"].update(values["-combo-"])
window.close()

Time.sleep() not pausing the correct moment?

Hello I have created a quiz using python and tkinter. After each option is pressed I wanted the correct answer to turn green and the three incorrect to turn red then revert to the default for the next question.The problem here being that running the code will take the buttons to the default before the user can see the colours. To do this I tried to use time.sleep() in the function however no matter where I use it it just seems to pause on the button being pressed down and then goes onto the next question without seeing any colour change.
Here is the relevant piece of code
def entry(num):
global score
global x
global count
count +=1
if Qa[x] == 1:
option1.config(bg = "green")
option2.config(bg = "red")
option3.config(bg="red")
option4.config(bg="red")
elif Qa[x] == 2:
option1.config(bg="red")
option2.config(bg="green")
option3.config(bg="red")
option4.config(bg="red")
elif Qa[x] == 3:
option1.config(bg="red")
option2.config(bg="red")
option3.config(bg="green")
option4.config(bg="red")
elif Qa[x] == 4:
option1.config(bg="red")
option2.config(bg="red")
option3.config(bg="red")
option4.config(bg="green")
if num == Qa[x]:
score += 1
x +=1
if count <10:
my_label.config(text = Qs[x])
option1.config(text = (question_prompts[x])[1],bg = "SystemButtonFace",command = lambda: entry(1) )
option2.config(text=(question_prompts[x])[2],bg = "SystemButtonFace",command = lambda: entry(2) )
option3.config(text=(question_prompts[x])[3],bg = "SystemButtonFace",command = lambda: entry(3) )
option4.config(text=(question_prompts[x])[4],bg = "SystemButtonFace",command = lambda: entry(4) )
else:
End_score =Label(text = "Well done you scored" +" "+ str(score)+" " +"out of 11", font = 40)
End_score.place(relx=0.5,rely =0.5,anchor = CENTER)
print(x,score, count, Qa[x])
I haven't put the time.sleep() in here because I have tried it everywhere in this section an it gives the same result
I would really appreciate some help
The PROBLEM here is that the options will not actually change color until Tk can get back to its main loop. As long as you are running your function, the main loop cannot pull new events. You need to set the colors, then use root.after to schedule a callback at some point in the future where you reset to all green.

Force users to select a file with PySimpleGui?

I'm new to PySimpleGui and I've searched every recipe for something that may help me and came up empty handed.
What I'm trying to do is: User will select a file, click a button and the app will do something with the file. This is what I have so far:
layout = [[sg.Text('Sistema'), sg.InputText(key='-file1-'), sg.FileBrowse()], [sg.Button("Go")]]
window = sg.Window('Test', layout)
while True:
event, values = window.read()
if event == "Go":
*do something with file1*
What I want is:
layout = [[sg.Text('Sistema'), sg.InputText(key='-file1-'), sg.FileBrowse()], [sg.Button("Go")]]
window = sg.Window('Test', layout)
while True:
event, values = window.read()
if values["-file1-"] == "":
print("You need to choose a file!")
*allow users to select a new file without closing the window*
if event == "Go":
*do something with file1*
What do I need to do? If I add a break statement, it leaves the while loop and closes the window. I need it to allow users to select a new file and read the window again. Is it possible?
Confirm filename OK or not when event Go in event loop.
Here, Cancel to cancel selection of a file, also stop Go.
from pathlib import Path
import PySimpleGUI as sg
sg.theme("DarkBlue")
layout = [
[sg.Text('Sistema'), sg.InputText(key='-file1-'), sg.FileBrowse()],
[sg.Button("Go")],
]
window = sg.Window('Test', layout)
while True:
event, values = window.read()
if event == sg.WINDOW_CLOSED:
break
elif event == "Go":
filename = values['-file1-']
while True:
if not Path(filename).is_file():
if filename == '':
sg.popup_ok('Select a file to go !')
else:
sg.popup_ok('File not exist !')
filename = sg.popup_get_file("", no_window=True)
if filename == '':
break
window['-file1-'].update(filename)
else:
print('File is ready !')
break
window.close()

Categories