【问题标题】:python/kivy: need function clock() but crash because of recursionpython/kivy:需要函数clock()但由于递归而崩溃
【发布时间】:2020-07-11 22:25:12
【问题描述】:

我是 python 和 kivy 的新手,并尝试从代码 sn-ps 和反复试验中学习。但现在我被困住了。 为了在树莓上显示天气和垃圾信息,我使用了 kivy。 为了获取这些信息,我使用了 URLRequest 函数。这个函数需要clock-function

    while not req.is_finished:
    Clock.tick()
    return req.result

所以程序可以工作,显示信息,但在大约 20 分钟左右后定期崩溃,并出现错误“RuntimeError:超出最大递归深度 但我不明白如何通过仍然让事情正常工作来摆脱递归:(

这里是上下文中的代码。有人可以帮忙吗?

    # -*- coding: utf-8 -*-
from kivy.app import App
from kivy.uix.label import Label
from kivy.clock import Clock
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.widget import Widget
from kivy.uix.textinput import TextInput
from kivy.network.urlrequest import UrlRequest
from time import gmtime, strftime, localtime, sleep

class garbage:
    def garbage_text(garbage):
        req = UrlRequest('http://192.168.1.1:8083/fhem?cmd={ReadingsVal(%22ABFALL%22,%22next_text%22,0)}&XHR=1&fwcsrf=password')
        while not req.is_finished:
            Clock.tick()
        return req.result

class weather:
    def weather_db1(weather):
        req = UrlRequest('http://192.168.1.1:8083/fhem?cmd={ReadingsVal(%22netatmo_M01_00_00_3f_1d_1a%22,%22temperature%22,0)}&XHR=1&fwcsrf=password')
        while not req.is_finished:
            Clock.tick()
        return req.result

class MyBox(BoxLayout):
    def update(self, *args):

        uweather = weather()
        aktw = uweather.weather_db1()

        ggarbage = garbage()
        garbagetext = ggarbage.garbage_text()


        self.ids.temp_ist.text = str(aktw)

        self.ids.uhrzeit_top.text = strftime("%H:%M", localtime())
        self.ids.datum_top.text = strftime("%d.%m.%Y", localtime())

        self.ids.garbage_std.text = garbagetext+" rausstellen "

class ControlApp(App):
    def build(self):
        actclock = MyBox()
        Clock.schedule_interval(actclock.update, 1)
        return actclock

if __name__ == "__main__":
    ControlApp().run()

【问题讨论】:

  • 你试过用req.wait()替换那个循环吗?
  • 我建议在update() 方法中添加代码来计时,以确保返回时间少于 1 秒。如果update()方法的返回时间超过1秒,那么Clock.schedule_interval()update()的调用就会慢慢堆积起来。
  • 您的代码没有正确缩进。你能解决这个问题吗?格式化是 Python 语法的一部分,所以它很重要(不同的缩进 = 不同的代码)。

标签: python kivy


【解决方案1】:

这是您的代码的修改版本,它使用回调而不是循环或等待:

from kivy.app import App
from kivy.lang import Builder
from kivy.clock import Clock, mainthread
from kivy.uix.boxlayout import BoxLayout
from kivy.network.urlrequest import UrlRequest
from time import strftime, localtime

class garbage:
    def garbage_text(self, *args):
        req = UrlRequest('http://192.168.1.1:8083/fhem?cmd={ReadingsVal(%22netatmo_M01_00_00_3f_1d_1a%22,%22temperature%22,0)}&XHR=1&fwcsrf=password',
            on_success=self.update, on_failure=self.failure)

    @mainthread
    def update(self, req, result):
        # update the GUI
        garbage_std = App.get_running_app().root.ids.garbage_std
        garbage_std.text = str(result)+" rausstellen "

        # schedule the next update
        Clock.schedule_once(self.garbage_text, 1)

    def failure(self):
        print('garbage failed')

class weather:
    def weather_db1(self, *args):
        req = UrlRequest('http://192.168.1.1:8083/fhem?cmd={ReadingsVal(%22netatmo_M01_00_00_3f_1d_1a%22,%22temperature%22,0)}&XHR=1&fwcsrf=password',
            on_success=self.update, on_failure=self.failure)

    @mainthread
    def update(self, req, result):
        # update the GUI
        temp_ist = App.get_running_app().root.ids.temp_ist
        temp_ist.text = str(result)

        # schedule the next update
        Clock.schedule_once(self.weather_db1, 1)

    def failure(self):
        print('weather failed')

class MyBox(BoxLayout):
    def update(self, *args):
        self.ids.uhrzeit_top.text = strftime("%H:%M", localtime())
        self.ids.datum_top.text = strftime("%d.%m.%Y", localtime())

class ControlApp(App):
    def build(self):
        actclock = MyBox()
        self.weather = weather()
        self.garbage = garbage()

        # start the time updates
        Clock.schedule_interval(actclock.update, 1)

        # start the other updates
        Clock.schedule_once(self.weather_update)
        Clock.schedule_once(self.garbage_update)

        return actclock

    def weather_update(self, dt):
        self.weather.weather_db1()

    def garbage_update(self, dt):
        self.garbage.garbage_text()

Builder.load_string('''
<MyBox>:
    orientation: 'vertical'
    Label:
        id: temp_ist
    Label:
        id: uhrzeit_top
    Label:
        id: datum_top
    Label:
        id: garbage_std
''')

if __name__ == "__main__":
    ControlApp().run()

【讨论】:

  • 非常感谢您的反馈!约翰安德森,req.wait 提示与您重新编写的代码一样有效!谢谢!!
  • req.wait() 的问题是它会阻止您的 GUI 运行。
猜你喜欢
  • 1970-01-01
  • 2011-11-09
  • 2011-11-24
  • 2023-03-30
  • 1970-01-01
  • 2015-09-08
  • 1970-01-01
  • 2019-05-14
相关资源
最近更新 更多