Reference error: weakly-referenced object no longer exists (Kivy)



  • Got an app for python 3.6 with kivy. PyCharm and linux launches and works, but prevents:

    [WARNING] Deprecated property "<StringProperty name=id>" of object "<kivy.uix.boxlayout.BoxLayout object at 0x00000288E8284DD8>" was accessed, it will be removed in a future version

    On the Androyde, when the button is pressed, add a recording to the OBD, closes the log.

    Reference error: weakly-referenced object no longer exists
    

    but the record is added to the database.

    The error occurs on the line

    self.task.add_widget(TaskLabel(id=str(self.i[0])))
    

    main.py

    from kivy.app import App
    from kivy.properties import StringProperty, ObjectProperty
    from kivy.uix.screenmanager import ScreenManager, Screen, SlideTransition
    from kivy.uix.anchorlayout import AnchorLayout
    from kivy.utils import get_color_from_hex
    from kivy.core.window import Window
    import sqlite3 #База данных
    import hashlib #Хеширование пароля
    from kivy.uix.boxlayout import BoxLayout
    import speech_recognition as sr #Голосовой ввод
    from gtts import gTTS
    import playsound
    import uuid #Генерация соли
    from re import * #Проверка на email
    

    ################################################################################
    Window.clearcolor = get_color_from_hex("#16203B")

    ################################################################################
    class Register(Screen):
    def disconnect(self):
    self.app = App.get_running_app()
    self.app.on_change_screen(self.manager.current, 'login', 'right')
    self.manager.get_screen('login').resetForm()

    def do_register(self, loginText, passwordText, email, password2):
        self.app = App.get_running_app()
    
        if(len(loginText) &lt; 5):
            #print('Имя пользователя должно содержать больше 4 символов')
            self.app.on_error("Ошибка: Имя пользователя должно содержать больше 4 символов", self.manager.current)
        else:
            if(len(passwordText) &lt; 6):
                #print('Пароль должен содержать больше 5 символов')
                self.app.on_error("Ошибка: Пароль должен содержать больше 5 символов", self.manager.current)
            else:
                if(passwordText != password2):
                    #print('Пароли не совпадают!')
                    self.app.on_error("Ошибка: Пароли не совпадают", self.manager.current)
                else:
                    self.pattern = compile('(^|\s)[-a-z0-9_.]+@([-a-z0-9]+\.)+[a-z]{2,6}(\s|$)')
                    self.email_valid = self.pattern.match(email)
                    if not self.email_valid:
                        #print('Email не поддерживается, введите другой')
                        self.app.on_error("Ошибка: Email не поддерживается, введите другой", self.manager.current)
                    else:
                        self.conn = sqlite3.connect("users.db")
                        self.cursor = self.conn.cursor()
    
                        self.rows = self.cursor.execute("SELECT COUNT(*) FROM users WHERE login=?", (loginText,)).fetchone()[0]
                        if(self.rows == 0):
    
                            def hash_password(password):
                                self.salt = uuid.uuid4().hex
                                return hashlib.sha256(self.salt.encode() + password.encode()).hexdigest() + ':' + self.salt
    
                            try:
                                self.cursor.execute("INSERT INTO users VALUES (NULL, ?, ?, ?)", (loginText, hash_password(passwordText), email))
                            except sqlite3.DatabaseError as error:
                                #print ("Ошибка: ", error)
                                self.app.on_error("Ошибка: " + error, self.manager.current)
                            else:
                                self.conn.commit()
                                self.cursor.close()
                                self.conn.close()
                                self.app.on_change_screen(self.manager.current, 'login', 'right')
                                self.manager.get_screen('login').resetForm()
                        else:
                            #print('Имя пользователя уже используется')
                            self.app.on_error("Ошибка: Имя пользователя уже используется", self.manager.current)
    

    ################################################################################
    class Connected(Screen):
    task = ObjectProperty(None)
    def init(self, *args, **kwargs):
    super(Connected, self).init(*args, **kwargs)

    def get_tasks_from_db(self):
        self.app = App.get_running_app()
        self.task.clear_widgets()
        self.conn = sqlite3.connect("users.db")
        self.cursor = self.conn.cursor()
        try:
            self.cursor.execute("SELECT id, task_text FROM tasks WHERE task_screen=? AND user_login =? ORDER BY id DESC", (self.manager.current, self.app.username))
        except sqlite3.DatabaseError as error:
            self.app.on_error("Ошибка: " + str(error), self.manager.current)
        else:
            self.rows = self.cursor.fetchall()
            for self.i in self.rows:
                self.app.TaskId = str(self.i[0])
                self.app.TaskText = str(self.i[1])
                self.task.add_widget(TaskLabel(id=str(self.i[0])))
            self.cursor.close()
            self.conn.close()
    
    def talk(self, file_name):
        playsound.playsound(file_name, True)
    
    def get_voice_text(self):
        self.is_speaking = True
        self.r = sr.Recognizer()
        self.talk("1.mp3")
        with sr.Microphone() as source:
            self.r.pause_threshold = 1
            #r.adjust_for_ambient_noise(source, duration=1)
            self.audio = self.r.listen(source)
        try:
            self.command = self.r.recognize_google(self.audio, language="ru-RU").lower()
            self.talk("2.mp3")
            self.add_task(self.command)
        except sr.UnknownValueError:
            self.talk("3.mp3")
        self.is_speaking = False
    
    def add_task(self, task_text):
        self.app = App.get_running_app()
        self.conn = sqlite3.connect("users.db")
        self.cursor = self.conn.cursor()
        if(len(task_text) &gt; 0):
            if(len(task_text) &lt; 56):
                try:
                    self.cursor.execute("INSERT INTO tasks VALUES (NULL, ?, ?, ?)", (task_text, self.manager.current, self.app.username))
                except sqlite3.DatabaseError as error:
                    self.app.on_error("Ошибка: " + error, self.manager.current)
                else:
                    self.conn.commit()
                    self.cursor.close()
                    self.conn.close()
                    self.get_tasks_from_db()
            else:
                self.app.on_error("Ошибка: Текст заметки не может быть длиннее 55 символов", self.manager.current)
        else:
            self.app.on_error("Ошибка: Текст заметки не задан", self.manager.current)
    
    def disconnect(self):
        self.app = App.get_running_app()
        self.app.on_change_screen(self.manager.current, 'login', 'right')
        self.manager.get_screen('login').resetForm()
    

    #################################################################################
    class TaskLabel(BoxLayout):
    def init(self, *args, **kwargs):
    super(TaskLabel, self).init(*args, **kwargs)

    def remove_task(self, id):
        self.app = App.get_running_app()
        self.conn = sqlite3.connect("users.db")
        self.cursor = self.conn.cursor()
        try:
            self.cursor.execute("DELETE FROM tasks WHERE id=?", (id,))
        except sqlite3.DatabaseError as error:
            self.app.on_error("Ошибка: " + (error), self.manager.current)
        else:
            self.conn.commit()
            self.cursor.close()
            self.conn.close()
    

    ################################################################################
    class Login(Screen):
    def init(self, *args, **kwargs):
    super(Login, self).init(*args, **kwargs)

    def do_login(self, loginText, passwordText):
        self.app = App.get_running_app()
        self.app.username = loginText
        self.app.password = passwordText
    
        self.conn = sqlite3.connect("users.db")
        self.cursor = self.conn.cursor()
        self.cursor_row = self.conn.cursor()
    
        self.cursor.execute("SELECT password FROM users WHERE login=?", (loginText,))
        self.rows = self.cursor_row.execute("SELECT COUNT(*) FROM users WHERE login=?", (loginText,)).fetchone()[0]
    
        if(self.rows &gt; 0):
            self.hashed_password = "".join(self.cursor.fetchone())
            self.pass_without_salt, self.salt = self.hashed_password.split(':')
            self.salt = "".join(self.salt)
            self.pass_without_salt = "".join(self.pass_without_salt)
    
            def hash_password(password, salt):
                return hashlib.sha256(salt.encode() + password.encode()).hexdigest()
    
            def checkPassword(password):
                if hash_password(password, self.salt) == self.pass_without_salt:
                    return True
    
    
            if((self.rows &gt; 0) and checkPassword(passwordText)):
                self.app.on_change_screen(self.manager.current, 'connected', 'left')
            else:
                self.app.on_error("Ошибка: Неверный логин или пароль", self.manager.current)
        self.cursor_row.close()
        self.cursor.close()
        self.conn.close()
    def resetForm(self):
        self.ids['login'].text = ""
        self.ids['password'].text = ""
    
    def do_register(self):
        self.app = App.get_running_app()
        self.app.on_change_screen(self.manager.current, 'register', 'left')
    

    ################################################################################
    class ErrorMessageWidget(AnchorLayout):
    pass
    ################################################################################
    class LoginApp(App):
    username = StringProperty(None)
    password = StringProperty(None)

    def __init__(self, *args, **kwargs):
        super(LoginApp, self).__init__(*args, **kwargs)
    
    def on_change_screen(self, screen, target_screen, transition):
        self.root.transition = SlideTransition(direction=transition)
        self.root.current = target_screen
        for child in self.root.get_screen(screen).children[:]:
            if child.id == 'error':
                self.root.get_screen(screen).remove_widget(child)
    
    def on_error(self, error, screen):
        self.ErrorMessage = error
        self.root.get_screen(screen).add_widget(ErrorMessageWidget(id='error'))
    
    
    def build(self):
        manager = ScreenManager()
    
        manager.add_widget(Login(name='login'))
        manager.add_widget(Connected(name='connected'))
        manager.add_widget(Register(name='register'))
    
        return manager
    

    ################################################################################
    if name == 'main':
    LoginApp().run()

    login.kv

    <Register>:
    BoxLayout
    id: register_layout
    orientation: 'vertical'
    padding: [10,50,10,50]
    spacing: 30

        Label:
            text: '\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044F'
            #Регистрация
            font_size: 32
            color: 0, 0, 0, 1
            size_hint_y: .1
    
        AnchorLayout:
            size_hint_y: .8
            BoxLayout:
                orientation: 'vertical'
                size_hint_y: None
                spacing: 10
                TextInput:
                    id: login
                    multiline:False
                    font_size: 20
                    hint_text: '\u041B\u043E\u0433\u0438\u043D'
                    size_hint_y: None
                    size_hint_x: .5
                    pos_hint: {'x': .25}
                    height: 40
                    padding: [5, 8]
    
                TextInput:
                    id: email
                    multiline:False
                    font_size: 20
                    hint_text: '\u042D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u0430\u044F\u0020\u043F\u043E\u0447\u0442\u0430'
                    size_hint_y: None
                    size_hint_x: .5
                    pos_hint: {'x': .25}
                    height: 40
                    padding: [5, 8]
    
                TextInput:
                    id: password
                    multiline:False
                    password:True
                    hint_text: '\u041F\u0430\u0440\u043E\u043B\u044C'
                    font_size: 20
                    size_hint_y: None
                    size_hint_x: .5
                    pos_hint: {'x': .25}
                    height: 40
    
                TextInput:
                    id: password_verify
                    multiline:False
                    password:True
                    hint_text: '\u041F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435\u0020\u043F\u0430\u0440\u043E\u043B\u044C'
                    font_size: 20
                    size_hint_y: None
                    size_hint_x: .5
                    pos_hint: {'x': .25}
                    height: 40
    
        BoxLayout:
            orientation: 'horizontal'
            spacing: 10
            size_hint_y: .1
            Button:
                text: '\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043E\u0432\u0430\u0442\u044C\u0441\u044F'
                #Зарегистрироваться
                font_size: 24
                color: 0, 0, 0, 1
                background_color: 1, 1, 1, .5
                on_press: root.do_register(login.text, password.text, email.text, password_verify.text)
            Button:
                text: "\u041D\u0430\u0437\u0430\u0434"
                #Назад
                font_size: 24
                color: 0, 0, 0, 1
                background_color: 1, 1, 1, .5
                on_press: root.disconnect()
    

    ################################################################################
    <Connected>:
    on_enter: root.get_tasks_from_db()
    task: task.self
    BoxLayout:
    orientation: 'vertical'
    spacing: 20
    padding: [10,50,10,50]
    Label:
    text: u"\u0412\u0432\u0435\u0434\u0438\u0442\u0435\u0020\u0442\u0435\u043A\u0441\u0442\u0020\u0437\u0430\u043C\u0435\u0442\u043A\u0438"
    #Введите текст заметки
    font_size: 24
    color: 0, 0, 0, 1
    size_hint_y: .1
    pos_hint: {'center_x': .5}
    BoxLayout:
    orientation: 'horizontal'
    size_hint_y: .2
    TextInput:
    id: task_input
    multiline:True
    font_size: 20
    padding: [5, 0]
    Button:
    text: 'Voice'
    on_press: root.get_voice_text()
    size_hint_x: .1
    color: 0, 0, 0, 1
    background_color: 1, 1, 1, .5
    BoxLayout:
    orientation: 'horizontal'
    size_hint_y: .1
    spacing: 20
    Button:
    text: u"\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C\u0020\u0437\u0430\u043C\u0435\u0442\u043A\u0443"
    #Добавить заметку
    font_size: 24
    color: 0, 0, 0, 1
    background_color: 1, 1, 1, .5
    on_press: root.add_task(task_input.text); task_input.text = ""
    Button:
    text: u"\u0421\u043C\u0435\u043D\u0438\u0442\u044C\u0020\u0430\u043A\u043A\u0430\u0443\u043D\u0442"
    #Сменить аккаунт
    font_size: 24
    color: 0, 0, 0, 1
    background_color: 1, 1, 1, .5
    on_press: root.disconnect()
    ScrollView:
    bar_width: 4
    scroll_type: ['bars']
    bar_inactive_color: 5, 20, 10, .5
    bar_color: 5, 10, 15, .8
    size_hint_y: .6
    BoxLayout:
    orientation: 'vertical'
    id: task
    size_hint_y: None
    height: self.minimum_height
    ################################################################################
    <TaskLabel>:
    size_hint_y: None
    height: 50
    canvas.before:
    Color:
    rgba: 0, 0, 0, 1
    Line:
    width: 1
    rectangle: self.x, self.y, self.width, self.height
    orientation: 'horizontal'
    Label:
    text_size: (self.width-20, self.height)
    halign: 'left'
    valign: 'middle'
    text: str(app.TaskText)
    font_size: 24
    color: 0, 0, 0, 1
    Button:
    text: "X"
    font_size: 24
    color: 0, 0, 0, 1
    size_hint: (.1, 1)
    background_color: 1, 1, 1, 0
    on_press: root.remove_task(root.id); root.parent.remove_widget(root);
    ################################################################################
    <Login>:
    BoxLayout
    id: login_layout
    orientation: 'vertical'
    padding: [10,50,10,50]
    spacing: 30
    Label:
    text: u'\u0410\u0432\u0442\u043E\u0440\u0438\u0437\u0430\u0446\u0438\u044F'
    #Авторизация
    font_size: 32
    color: 0, 0, 0, 1
    size_hint_y: .1
    AnchorLayout:
    size_hint_y: .8
    BoxLayout:
    orientation: 'vertical'
    size_hint_y: None
    spacing: 10
    TextInput:
    id: login
    multiline:False
    font_size: 20
    hint_text: '\u041B\u043E\u0433\u0438\u043D'
    size_hint_y: None
    size_hint_x: .5
    pos_hint: {'x': .25}
    height: 40
    padding: [5, 8]

                TextInput:
                    id: password
                    multiline:False
                    password:True
                    hint_text: '\u041F\u0430\u0440\u043E\u043B\u044C'
                    font_size: 20
                    size_hint_y: None
                    size_hint_x: .5
                    pos_hint: {'x': .25}
                    height: 40
    
        BoxLayout:
            orientation: 'horizontal'
            spacing: 10
            size_hint_y: .1
            Button:
                text: '\u0412\u043E\u0439\u0442\u0438'
                #Войти
                font_size: 24
                color: 0, 0, 0, 1
                background_color: 1, 1, 1, .5
                on_press: root.do_login(login.text, password.text)
            Button:
                text: '\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044F'
                #Регистрация
                font_size: 24
                color: 0, 0, 0, 1
                background_color: 1, 1, 1, .5
                on_press: root.do_register()
    

    <ErrorMessageWidget>:
    anchor_x: "center"
    anchor_y: "top"
    Button:
    text: app.ErrorMessage
    background_color: 1, 0, 0, 1
    size_hint_y: .05
    on_press: root.parent.remove_widget(root)



  • Reset the linux, set up xubuntu, removed some dependence in buildozer.spec, and the problem solved.




Suggested Topics

  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2