简体   繁体   中英

How can be solved this NameError of Kivy, Python?

Code

'''IMPORTAR MÓDULOS Y CREAR VARIABLES'''

#Modulos Kivy
from kivy.app import App
from kivy.uix.screenmanager import Screen,ScreenManager
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
from kivy.clock import Clock
from datetime import datetime, date, time
from kivy.animation import Animation
from time import perf_counter,sleep

#Crear variable de instrucciones
txt_instruction = '''
1 - Answer some questions.
2 - Text your breathing.
3 - Test your pulse.
4 - Run for 5 minutes.
5 - Test your pulse.
6 - Run for 5 minutes.
7 - Test your pulse.
8 - Text your breathing.
'''
#Crear test de ruffier
txt_index = "Your ruffier index: "
txt_workheart = "Your pulse: "
txt_nodata = "There is no data for your age!"
txt_res = []
txt_res.append("DEAD")
txt_res.append("BAD")
txt_res.append("OK")
txt_res.append("GOOD")
txt_res.append("PERFECT")

def ruffier_index_func(P1, P2, P3):
    return ((4 * (P1 + P2 + P3)) / 10)
def neud_level(age):
    norm_age = (min(age,15)-7)//2
    result = 21 - norm_age * 1.5
    return result
def ruffier_result(r_index, level):
    if r_index >= level:
        return 0
    level = level - 4
    if r_index >= level:
        return 1
    level = level - 5
    if r_index >= level:
        return 2
    level = level - 5.5
    if r_index >= level:
        return 3
    return 4
def test(P1, P2, P3, B1, B2, age):
    if age < 5:
        return (txt_index + "0", txt_nodata)
    else:
        ruff_index = ruffier_index_func(P1,P2,P3)
        result = txt_res[int(ruffier_result(ruff_index,neud_level(age)))]
        res = str(txt_res[result]) + "\n" + str(result) + "\n" + txt_workheart + str(ruff_index)
        return res



'''CREAR BUTTONS'''

#Button
class NextButton(Button):
    def __init__(self,scr,dir,goal,**kwargs):
        super().__init__(**kwargs)
        self.scr = scr
        self.dir = dir
        self.goal = goal
        self.ok = True
        self.result = int()
    def on_release(self):
        if self.ok == True:
            self.scr.manager.transition.dir = self.dir
            self.scr.manager.current = self.goal



'''CREAR SCREENS'''

#Bienvenida
class SCRMain1(Screen):
    def __init__(self,name="main1"):
        super().__init__(name=name)
        self.create()
    def create(self):
        title = Label(text="EXER",font_size ="100sp",color = [0.5,0.5,1,1])
        nextBut = NextButton(self,"left","main2",text="START",font_size = "50sp",background_color = [0.8,0.8,0,1],size_hint = (.5,.4),pos_hint = {"center_x":0.5})
        None1 = Label(font_size="20sp")
        None2 = Label(font_size="20sp")
        mainLay = BoxLayout(orientation="vertical",padding="0sp",spacing="0sp")
        mainLay.add_widget(None1)
        mainLay.add_widget(title)
        mainLay.add_widget(nextBut)
        mainLay.add_widget(None2)
        self.add_widget(mainLay)
#Instrucciones
class SCRMain2(Screen):
    def __init__(self,name="main2"):
        super().__init__(name=name)
        title = Label(text="INSTRUCTIONS",font_size ="50sp",color = [0.5,0.5,1,1])
        lab = Label(text="",font_size ="20sp",color = [0.5,1,1,1])
        try:
            lab.text = txt_instruction
        except:
            lab.text = txtIns
        but = NextButton(self,"left","you",text="GO",font_size = "25sp",background_color = [0.8,0.8,0,1])
        mainLay = BoxLayout(orientation="vertical",padding="0sp",spacing="20sp")
        mainLay.add_widget(title)
        mainLay.add_widget(lab)
        mainLay.add_widget(but)
        self.add_widget(mainLay)
#Nombre,sexo,edad
class SCRYou(Screen):
    def __init__(self,name="you"):
        super().__init__(name=name)
        lab = Label(text="\nQUESTIONS",font_size ="50sp",color = [0.5,0.5,1,1])
        self.w1 = TextInput(text="NAME",multiline=False)
        self.w2 = TextInput(text="AGE",multiline=False)
        self.o1 = ToggleButton(text='Boy',group="sex")
        self.o2 = ToggleButton(text='Girl',group="sex")
        but = NextButton(self,"left","scr1",text="NEXT",font_size = "50sp",background_color = [0.8,0.8,0,1],size_hint=(1,.5))
        mainLay = BoxLayout(orientation="vertical",padding="0sp",spacing="0sp")
        hLay = BoxLayout(orientation="horizontal",padding="0sp",spacing="0sp")
        vLay1 = BoxLayout(orientation="vertical",padding="0sp",spacing="0sp")
        choiceLay = BoxLayout(orientation="horizontal",padding="0sp",spacing="0sp")
        mainLay = BoxLayout(orientation="vertical",padding="0sp",spacing="0sp")
        mainLay.add_widget(lab)
        vLay1.add_widget(self.w1)
        vLay1.add_widget(self.w2)
        choiceLay.add_widget(self.o1)
        choiceLay.add_widget(self.o2)
        vLay1.add_widget(choiceLay)
        hLay.add_widget(vLay1)
        mainLay.add_widget(hLay)
        mainLay.add_widget(but)
        self.add_widget(mainLay)
    def on_leave(self):
        global Name, Age, Sex
        Name = self.w1.text
        Age = self.w2.text
        if self.o1.state == "normal" and self.o2.state == "normal":
            Sex = "1"
        if self.o1.state == "down":
            Sex = "20"
        elif self.o2.state == "down":
            Sex = "10"
        self.w1.text = "NAME"
        self.w2.text = "AGE"
        self.o1.state = "normal"
        self.o2.state = "normal"
#Respirar1
class SCR1(Screen):
    def __init__(self,name="scr1"):
        super().__init__(name=name)
        title = Label(text="\nBREATHING",font_size ="50sp",color = [0.5,0.5,1,1])
        self.ans = TextInput(text="",multiline=False,font_size ="100sp",size_hint=(1,1),pos_hint={"center_x":0.5},halign = 'center')
        but = NextButton(self,"left","scr2",text="NEXT",font_size = "50sp",background_color = [0.8,0.8,0,1],size_hint = (1,.5),pos_hint = {"center_x":0.5})
        mainLay = BoxLayout(orientation="vertical",padding="0sp",spacing="0sp")
        mainLay.add_widget(title)
        mainLay.add_widget(self.ans)
        mainLay.add_widget(but)
        self.add_widget(mainLay)
    def on_leave(self):
        global Respirar1
        Respirar1 = self.ans.text
        self.ans.text = ""
#Pulsaciones1
class SCR2(Screen):
    def __init__(self,name="scr2"):
        super().__init__(name=name)
        title = Label(text="\nPULSE",font_size ="50sp",color = [0.5,0.5,1,1])
        self.ans = TextInput(text="",multiline=False,font_size ="100sp",size_hint=(1,1),pos_hint={"center_x":0.5},halign = 'center')
        but = NextButton(self,"left","scr3",text="NEXT",font_size = "50sp",background_color = [0.8,0.8,0,1],size_hint = (1,.5),pos_hint = {"center_x":0.5})
        mainLay = BoxLayout(orientation="vertical",padding="0sp",spacing="0sp")
        mainLay.add_widget(title)
        mainLay.add_widget(self.ans)
        mainLay.add_widget(but)
        self.add_widget(mainLay)
    def on_leave(self):
        global Pulsaciones1
        Pulsaciones1 = self.ans.text
        self.ans.text = ""
#Correr1
class SCR3(Screen):
    def __init__(self,name="scr3"):
        super().__init__(name=name)
        title = Label(text="\nRUN",font_size ="50sp",color = [0.5,0.5,1,1])
        clock = Label(text="05:00",font_size ="100sp",color = [0.5,1,1,1])
        but = NextButton(self,"left","scr4",text="NEXT",font_size = "50sp",background_color = [0.8,0.8,0,1],size_hint = (1,.5),pos_hint = {"center_x":0.5})
        mainLay = BoxLayout(orientation="vertical",padding="0sp",spacing="0sp")
        mainLay.add_widget(title)
        mainLay.add_widget(clock)
        mainLay.add_widget(but)
        self.add_widget(mainLay)
#Pulsaciones2
class SCR4(Screen):
    def __init__(self,name="scr4"):
        super().__init__(name=name)
        title = Label(text="\nPULSE",font_size ="50sp",color = [0.5,0.5,1,1])
        self.ans = TextInput(text="",multiline=False,font_size ="100sp",size_hint=(1,1),pos_hint={"center_x":0.5},halign = 'center')
        but = NextButton(self,"left","scr5",text="NEXT",font_size = "50sp",background_color = [0.8,0.8,0,1],size_hint = (1,.5),pos_hint = {"center_x":0.5})
        mainLay = BoxLayout(orientation="vertical",padding="0sp",spacing="0sp")
        mainLay.add_widget(title)
        mainLay.add_widget(self.ans)
        mainLay.add_widget(but)
        self.add_widget(mainLay)
    def on_leave(self):
        global Pulsaciones2
        Pulsaciones2 = self.ans.text
        self.ans.text = ""
#Correr2
class SCR5(Screen):
    def __init__(self,name="scr5"):
        super().__init__(name=name)
        global clock
        title = Label(text="\nRUN",font_size ="50sp",color = [0.5,0.5,1,1])
        clock = Label(text="05:00",font_size ="100sp",color = [0.5,1,1,1])
        but = NextButton(self,"left","scr6",text="NEXT",font_size = "50sp",background_color = [0.8,0.8,0,1],size_hint = (1,.5),pos_hint = {"center_x":0.5})
        mainLay = BoxLayout(orientation="vertical",padding="0sp",spacing="0sp")
        mainLay.add_widget(title)
        mainLay.add_widget(clock)
        mainLay.add_widget(but)
        self.add_widget(mainLay)
#Pulsaciones3
class SCR6(Screen):
    def __init__(self,name="scr6"):
        super().__init__(name=name)
        title = Label(text="\nPULSE",font_size ="50sp",color = [0.5,0.5,1,1])
        self.ans = TextInput(text="",multiline=False,font_size ="100sp",size_hint=(1,1),pos_hint={"center_x":0.5},halign = 'center')
        but = NextButton(self,"left","scr7",text="NEXT",font_size = "50sp",background_color = [0.8,0.8,0,1],size_hint = (1,.5),pos_hint = {"center_x":0.5})
        mainLay = BoxLayout(orientation="vertical",padding="0sp",spacing="0sp")
        mainLay.add_widget(title)
        mainLay.add_widget(self.ans)
        mainLay.add_widget(but)
        self.add_widget(mainLay)
    def on_leave(self):
        global Pulsaciones3
        Pulsaciones3 = self.ans.text
        self.ans.text = ""
#Respirar2
class SCR7(Screen):
    def __init__(self,name="scr7"):
        super().__init__(name=name)
        title = Label(text="\nBREATHING",font_size ="50sp",color = [0.5,0.5,1,1])
        self.ans = TextInput(text="",multiline=False,font_size ="100sp",size_hint=(1,1),pos_hint={"center_x":0.5},halign = 'center')
        but = NextButton(self,"left","scr8",text="NEXT",font_size = "50sp",background_color = [0.8,0.8,0,1],size_hint = (1,.5),pos_hint = {"center_x":0.5})
        mainLay = BoxLayout(orientation="vertical",padding="0sp",spacing="0sp")
        mainLay.add_widget(title)
        mainLay.add_widget(self.ans)
        mainLay.add_widget(but)
        self.add_widget(mainLay)
    def on_leave(self):
        global Respirar2
        Respirar2 = self.ans.text
        self.ans.text = ""
#Resultado
class SCR8(Screen):
    def __init__(self,name="scr8"):
        super().__init__(name=name)
        lab = Label(text="Resultado",font_size ="50sp",color = [0.5,0.5,1,1])
        but = NextButton(self,"left","end",text="NEXT",font_size = "50sp",background_color = [0.8,0.8,0,1],size_hint = (.5,.4),pos_hint = {"center_x":0.5})
        self.result = Label(text="",font_size ="20sp",color = [0.5,1,1,1])
        None1 = Label(font_size="20sp")
        None2 = Label(font_size="20sp")
        mainLay = BoxLayout(orientation="vertical",padding="0sp",spacing="0sp")
        mainLay.add_widget(None1)
        mainLay.add_widget(lab)
        mainLay.add_widget(self.result)
        mainLay.add_widget(but)
        mainLay.add_widget(None2)
        self.add_widget(mainLay)
    def on_enter(self):
        resultValue = test(int(Pulsaciones1),int(Pulsaciones2),int(Pulsaciones3),int(Respirar1),int(Respirar2),int(Age))
        self.result.text = str(resultValue)
#Felicitar
class SCREnd(Screen):
    def __init__(self,name="end"):
        super().__init__(name=name)
        lab = Label(text="CONGRATULATIONS",font_size ="50sp",color = [0.5,0.5,1,1])
        but = NextButton(self,"left","main1",text="RESTART",font_size = "50sp",background_color = [0.8,0.8,0,1],size_hint = (.5,.4),pos_hint = {"center_x":0.5})
        None1 = Label(font_size="20sp")
        None2 = Label(font_size="20sp")
        mainLay = BoxLayout(orientation="vertical",padding="0sp",spacing="0sp")
        mainLay.add_widget(None1)
        mainLay.add_widget(lab)
        mainLay.add_widget(but)
        mainLay.add_widget(None2)
        self.add_widget(mainLay)



'''CREAR APP'''

#Crear
class MyApp(App):
    def build(self):
        sm = ScreenManager()
        sm.add_widget(SCRMain1(name="main1"))
        sm.add_widget(SCRMain2(name="main2"))
        sm.add_widget(SCRYou(name="you"))
        sm.add_widget(SCR1(name="scr1"))
        sm.add_widget(SCR2(name="scr2"))
        sm.add_widget(SCR3(name="scr3"))
        sm.add_widget(SCR4(name="scr4"))
        sm.add_widget(SCR5(name="scr5"))
        sm.add_widget(SCR6(name="scr6"))
        sm.add_widget(SCR7(name="scr7"))
        sm.add_widget(SCR8(name="scr8"))
        sm.add_widget(SCREnd(name="end"))
        sm.current = "main1"
        return sm

#Ejecutar
app = MyApp()
app.title = "EXER"
app.run()

Error

(...) line 283, in on_enter
NameError: name 'Respirar2' is not defined

It gives the NameError for the global variable created in SCR7 (always the class before the SCR8 class, where the error happens).

Question

I believe it may be a problem of global variables and there might be a problem with the function on_leave , as the on_enter works.

It seems the value of the variable is not assigned.

What can I do to solve this?

The reson is because SCR8 > on_enter is called earlier by Kivy than SCR7 > on_leave . Just replace those methods content with print('entering SCR8', flush=True) and print('leaving SCR7', flush=True) to see what is executed first. I agree, it may dissappoint, but you cannot assume that while changing a screen on_leave will be executed before on_enter .

As a fast and dirty workaround you may replace def on_leave(self): within class SCR7(Screen): with def on_pre_leave(self):

BTW. In general it would be better to hold values for example as screen manager attributes or app attributes instead of global variables.

Under the line sm = ScreenManager() define your attributes like this:

sm.Name, sm.Age, sm.Sex = None, None, None
sm.Pulsaciones1, sm.Pulsaciones2, sm.Pulsaciones3, sm.Respirar1, sm.Respirar2 = None, None, None, None, None

Then remove your global Name, Age, Sex , global Respirar1 , global Pulsaciones1 , global Pulsaciones2 , global Pulsaciones3 , global Respirar2 lines, and replace all occurences of:

Name with self.manager.Name

Age with self.manager.Age

Sex with self.manager.Sex

Respirar1 with self.manager.Respirar1

Respirar2 with self.manager.Respirar2

Pulsaciones1 with self.manager.Pulsaciones1

Pulsaciones2 with self.manager.Pulsaciones2

Pulsaciones3 with self.manager.Pulsaciones3

Congrats, you are not using global variables anymore:)

It is considered bad-practice to use globals.

Issue explains

You define the global variable in a callback function of class SCR7 which might not be called. At least this function is not called at startup.

    def on_leave(self):
        global Respirar2
        Respirar2 = self.ans.text
        self.ans.text = ""

But when your variable Respirar2 is read in a different class SCR8 , in the callback function on_enter , then it is not yet defined:

    def on_enter(self):
        resultValue = test(int(Pulsaciones1),int(Pulsaciones2),int(Pulsaciones3),int(Respirar1),int(Respirar2),int(Age))
        self.result.text = str(resultValue)

Fix

Define the global outside the classes and initialise with a default value like empty string '' or zero '0' :

#Crear variable de instrucciones

Respirar2 = ''  # later written by SCR7 and read by SCR8 

Then you can remove the global Respirar2 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM