nonetype object not subscriptable pysimplegui
Question:
I’m trying to learn python and pysimplegui at the same time. Also I am old which doesn’t help!
I am writing a practice program with my 10 year old son(blind leading the blind) and am running into a problem which i cant fix.
Basically the program lets you enter how many numbers to pick from and how many numbers to pick, then calculates the odds of winning. Hit generate to randomly pick the numbers for you and Print the results to a txt file for a record of your picks.
It all works fine but when i close the window i get a nonetype error which I can’t work out.
Can any of ye genius’s help?
This is the offending line
n=int(values[‘–tn–‘])
from os import close
import random
from tkinter import Scrollbar
import PySimpleGUI as sg
import datetime
import math
from time import sleep, time
from PySimpleGUI.PySimpleGUI import Open, WIN_CLOSED, main
import sys
sg.theme('Reddit')
layout = [
[sg.In(size=(5,1),k="--tn--" ) ]+[sg.Text('Enter total amount of
numbers',size=(35,1))],
[sg.In(size=(5,1),k="--pn--")]+[sg.Text('Enter how many numbers
you are picking',size=(35,1))],
[sg.Text('Win odds')]+[sg.ML(background_color='light
coral',text_color='white',key='--oddout--',size=(50,2))],
[sg.ML(size=(20,30), key='--main--')],
[sg.Submit('Odds',key='--odds--')]+[sg.Submit('Generate',key='--
gen--')]+ [sg.Cancel('Cancel')]+[sg.Save(key='--save--')]+
[sg.CloseButton('Close',pad=(100,0))]
]
window = sg.Window('Lotto number generator',layout)
while True:
event, values = window.read()
n=int(values['--tn--'])
rr=int(values['--pn--'])
nf = math.factorial(n)
rf = math.factorial(rr)
winodds = (nf/(rf*math.factorial(n-rr)))
winodds = int(winodds)
now = datetime.datetime.now()
if event == WIN_CLOSED:
window['--tn--'].update('1')
break
if event == '--gen--':
r = random.sample(range(1,n),rr)
for i in r:
window['--main--'].print(i)
if event == '--odds--':
window['--oddout--'].print("Your chances of winning are
",f'{winodds:,d}', " to 1, Good Luck")
if event == 'Cancel':
window['--oddout--'].update('')
window['--tn--'].update('')
window['--pn--'].update('')
if event == '--save--':
sys.stdout = open("lotto.txt", "w")
print(values['--main--'])
sys.stdout=close(fd=0)
window.close()
Answers:
There’re something not good,
- You should check the window close event first, not to processing
event, values
for other cases first, like following code. You may get event, values
as None, None
if not, then values['--tn--']
will be same as None['--tn--']
. That’s why you got TypeError: 'NoneType' object is not subscriptable
.
while True:
event, values = window.read()
if event in (sg.WINDOW_CLOSED, 'Close'):
break
# process other events from here
window.close()
- In your input fields,
values['--tn--']
or values['--pn--']
maybe not with correct format for integer number, so following code may get failure ValueError: invalid literal for int() with base 10
n=int(values['--tn--'])
rr=int(values['--pn--'])
Here’s my way to avoid issue,
def integer(string):
try:
value = int(string)
except:
value = None
return value
for string in ("10.5", "", "10"):
value = integer(string)
if value is None:
print(f"{repr(string)} is not a legal integer string !")
else:
print(f"{repr(string)} converted to {value} !")
'10.5' is not a legal integer string !
'' is not a legal integer string !
'10' converted to 10 !
- Basically, window destroied after you click close button
X
of window, so you should not update anything on it.
if event == WIN_CLOSED:
# window['--tn--'].update('1')
break
event, values = window.read()
is returning None
. None['--tn--']
does not exist as it doesn’t make sense for None
to have a property, hence the error message. You have used the test to avoid this but moved it below an attempt to use the missing property. Hence the error.
It’s also worth using a linting tool prompt you to make adjustments to syntax that will break your code and good practice warnings. I use pylint and flake8. The following addresses your specific error message with some tidying for the linter messages. There are still some warnings – good learning exercise :).
"""Learning program."""
from os import close
import random
import PySimpleGUI as sg
import datetime
import math
from PySimpleGUI.PySimpleGUI import Open, WIN_CLOSED, main
import sys
sg.theme('Reddit')
layout = [
[sg.In(size=(5, 1), k="--tn--")] +
[sg.Text('Enter total amount of numbers', size=(35, 1))],
[sg.In(size=(5, 1), k="--pn--")] +
[sg.Text('Enter how many numbers you are picking', size=(35, 1))],
[sg.Text('Win odds')] +
[sg.ML(
background_color='light coral', text_color='white', key='--oddout--', size=(50, 2)
)],
[sg.ML(size=(20, 30), key='--main--')],
[sg.Submit('Odds', key='--odds--')] +
[sg.Submit('Generate', key='--gen--')] +
[sg.Cancel('Cancel')] +
[sg.Save(key='--save--')] +
[sg.CloseButton('Close', pad=(100, 0))]
]
window = sg.Window('Lotto number generator', layout)
while True:
event, values = window.read()
# Moved the next three lines up and commented update which also errors
if event == WIN_CLOSED:
# window['--tn--'].update('1')
break
n = int(values['--tn--'])
rr = int(values['--pn--'])
nf = math.factorial(n)
rf = math.factorial(rr)
winodds = (nf/(rf*math.factorial(n-rr)))
winodds = int(winodds)
now = datetime.datetime.now()
if event == '--gen--':
r = random.sample(range(1, n), rr)
for i in r:
window['--main--'].print(i)
if event == '--odds--':
window['--oddout--'].print(
"Your chances of winning are", f'{winodds:,d}', " to 1, Good Luck"
)
if event == 'Cancel':
window['--oddout--'].update('')
window['--tn--'].update('')
window['--pn--'].update('')
if event == '--save--':
sys.stdout = open("lotto.txt", "w")
print(values['--main--'])
sys.stdout = close(fd=0)
window.close()
Flake8 in particular will prompt you to follow practices that don’t have an obvious practical purpose. Later as you use more of the language the benefit of flake8 prompts are good habits that eventually pay large benefits.
When you close a window, event
and values
are not set, see my example below.
While debugging, it’s a good practice to print out the current values of event
and values
to be able to check whether you get what you thought you’d get, like this:
def test():
layout = [[sg.In(size=(5, 1), k="--tn--"), sg.Text('Enter total amount of numbers', size=(35, 1))],
[sg.In(size=(5, 1), k="--pn--"), sg.Text('Enter how many numbers you are picking', size=(35, 1))],
[sg.Text('Win odds'),
sg.ML(background_color='light coral', text_color='white', key='--oddout--', size=(50, 2))],
[sg.ML(size=(20, 30), key='--main--')],
[sg.Submit('Odds', key='--odds--'), sg.Submit('Generate', key='--gen--'),
sg.Cancel('Cancel'), sg.Save(key=' - -save - -'), sg.CloseButton('Close', pad=(100, 0))]
]
window = sg.Window('Lotto number generator', layout)
while True:
event, values = window.read()
print(f'event = {event}, values = {values}')
if event == WIN_CLOSED:
break
window.close()
When you close the window, you get
event = None, values = {'--tn--': None, '--pn--': None, '--oddout--': None, '--main--': None}
so, it is important to start your main loop with if event == WIN_CLOSED:
(and break the loop in that case). Only after that, you can go on to process various events and values.
It happens when the value is not given and you closed the program. The easiest way is to give a random value.
input_box = sg.InputText(tooltip="Enter text", key='text')
while True:
event, value = window.read()
match event:
case WIN_CLOSED:
value['text'] = 1 # <- a random value
break
I’m trying to learn python and pysimplegui at the same time. Also I am old which doesn’t help!
I am writing a practice program with my 10 year old son(blind leading the blind) and am running into a problem which i cant fix.
Basically the program lets you enter how many numbers to pick from and how many numbers to pick, then calculates the odds of winning. Hit generate to randomly pick the numbers for you and Print the results to a txt file for a record of your picks.
It all works fine but when i close the window i get a nonetype error which I can’t work out.
Can any of ye genius’s help?
This is the offending line
n=int(values[‘–tn–‘])
from os import close
import random
from tkinter import Scrollbar
import PySimpleGUI as sg
import datetime
import math
from time import sleep, time
from PySimpleGUI.PySimpleGUI import Open, WIN_CLOSED, main
import sys
sg.theme('Reddit')
layout = [
[sg.In(size=(5,1),k="--tn--" ) ]+[sg.Text('Enter total amount of
numbers',size=(35,1))],
[sg.In(size=(5,1),k="--pn--")]+[sg.Text('Enter how many numbers
you are picking',size=(35,1))],
[sg.Text('Win odds')]+[sg.ML(background_color='light
coral',text_color='white',key='--oddout--',size=(50,2))],
[sg.ML(size=(20,30), key='--main--')],
[sg.Submit('Odds',key='--odds--')]+[sg.Submit('Generate',key='--
gen--')]+ [sg.Cancel('Cancel')]+[sg.Save(key='--save--')]+
[sg.CloseButton('Close',pad=(100,0))]
]
window = sg.Window('Lotto number generator',layout)
while True:
event, values = window.read()
n=int(values['--tn--'])
rr=int(values['--pn--'])
nf = math.factorial(n)
rf = math.factorial(rr)
winodds = (nf/(rf*math.factorial(n-rr)))
winodds = int(winodds)
now = datetime.datetime.now()
if event == WIN_CLOSED:
window['--tn--'].update('1')
break
if event == '--gen--':
r = random.sample(range(1,n),rr)
for i in r:
window['--main--'].print(i)
if event == '--odds--':
window['--oddout--'].print("Your chances of winning are
",f'{winodds:,d}', " to 1, Good Luck")
if event == 'Cancel':
window['--oddout--'].update('')
window['--tn--'].update('')
window['--pn--'].update('')
if event == '--save--':
sys.stdout = open("lotto.txt", "w")
print(values['--main--'])
sys.stdout=close(fd=0)
window.close()
There’re something not good,
- You should check the window close event first, not to processing
event, values
for other cases first, like following code. You may getevent, values
asNone, None
if not, thenvalues['--tn--']
will be same asNone['--tn--']
. That’s why you gotTypeError: 'NoneType' object is not subscriptable
.
while True:
event, values = window.read()
if event in (sg.WINDOW_CLOSED, 'Close'):
break
# process other events from here
window.close()
- In your input fields,
values['--tn--']
orvalues['--pn--']
maybe not with correct format for integer number, so following code may get failureValueError: invalid literal for int() with base 10
n=int(values['--tn--'])
rr=int(values['--pn--'])
Here’s my way to avoid issue,
def integer(string):
try:
value = int(string)
except:
value = None
return value
for string in ("10.5", "", "10"):
value = integer(string)
if value is None:
print(f"{repr(string)} is not a legal integer string !")
else:
print(f"{repr(string)} converted to {value} !")
'10.5' is not a legal integer string !
'' is not a legal integer string !
'10' converted to 10 !
- Basically, window destroied after you click close button
X
of window, so you should not update anything on it.
if event == WIN_CLOSED:
# window['--tn--'].update('1')
break
event, values = window.read()
is returning None
. None['--tn--']
does not exist as it doesn’t make sense for None
to have a property, hence the error message. You have used the test to avoid this but moved it below an attempt to use the missing property. Hence the error.
It’s also worth using a linting tool prompt you to make adjustments to syntax that will break your code and good practice warnings. I use pylint and flake8. The following addresses your specific error message with some tidying for the linter messages. There are still some warnings – good learning exercise :).
"""Learning program."""
from os import close
import random
import PySimpleGUI as sg
import datetime
import math
from PySimpleGUI.PySimpleGUI import Open, WIN_CLOSED, main
import sys
sg.theme('Reddit')
layout = [
[sg.In(size=(5, 1), k="--tn--")] +
[sg.Text('Enter total amount of numbers', size=(35, 1))],
[sg.In(size=(5, 1), k="--pn--")] +
[sg.Text('Enter how many numbers you are picking', size=(35, 1))],
[sg.Text('Win odds')] +
[sg.ML(
background_color='light coral', text_color='white', key='--oddout--', size=(50, 2)
)],
[sg.ML(size=(20, 30), key='--main--')],
[sg.Submit('Odds', key='--odds--')] +
[sg.Submit('Generate', key='--gen--')] +
[sg.Cancel('Cancel')] +
[sg.Save(key='--save--')] +
[sg.CloseButton('Close', pad=(100, 0))]
]
window = sg.Window('Lotto number generator', layout)
while True:
event, values = window.read()
# Moved the next three lines up and commented update which also errors
if event == WIN_CLOSED:
# window['--tn--'].update('1')
break
n = int(values['--tn--'])
rr = int(values['--pn--'])
nf = math.factorial(n)
rf = math.factorial(rr)
winodds = (nf/(rf*math.factorial(n-rr)))
winodds = int(winodds)
now = datetime.datetime.now()
if event == '--gen--':
r = random.sample(range(1, n), rr)
for i in r:
window['--main--'].print(i)
if event == '--odds--':
window['--oddout--'].print(
"Your chances of winning are", f'{winodds:,d}', " to 1, Good Luck"
)
if event == 'Cancel':
window['--oddout--'].update('')
window['--tn--'].update('')
window['--pn--'].update('')
if event == '--save--':
sys.stdout = open("lotto.txt", "w")
print(values['--main--'])
sys.stdout = close(fd=0)
window.close()
Flake8 in particular will prompt you to follow practices that don’t have an obvious practical purpose. Later as you use more of the language the benefit of flake8 prompts are good habits that eventually pay large benefits.
When you close a window, event
and values
are not set, see my example below.
While debugging, it’s a good practice to print out the current values of event
and values
to be able to check whether you get what you thought you’d get, like this:
def test():
layout = [[sg.In(size=(5, 1), k="--tn--"), sg.Text('Enter total amount of numbers', size=(35, 1))],
[sg.In(size=(5, 1), k="--pn--"), sg.Text('Enter how many numbers you are picking', size=(35, 1))],
[sg.Text('Win odds'),
sg.ML(background_color='light coral', text_color='white', key='--oddout--', size=(50, 2))],
[sg.ML(size=(20, 30), key='--main--')],
[sg.Submit('Odds', key='--odds--'), sg.Submit('Generate', key='--gen--'),
sg.Cancel('Cancel'), sg.Save(key=' - -save - -'), sg.CloseButton('Close', pad=(100, 0))]
]
window = sg.Window('Lotto number generator', layout)
while True:
event, values = window.read()
print(f'event = {event}, values = {values}')
if event == WIN_CLOSED:
break
window.close()
When you close the window, you get
event = None, values = {'--tn--': None, '--pn--': None, '--oddout--': None, '--main--': None}
so, it is important to start your main loop with if event == WIN_CLOSED:
(and break the loop in that case). Only after that, you can go on to process various events and values.
It happens when the value is not given and you closed the program. The easiest way is to give a random value.
input_box = sg.InputText(tooltip="Enter text", key='text')
while True:
event, value = window.read()
match event:
case WIN_CLOSED:
value['text'] = 1 # <- a random value
break