Kivy+mqtt打开_消息时,出现致命Python错误:(pygame降落伞)分段错误

Kivy+mqtt打开_消息时,出现致命Python错误:(pygame降落伞)分段错误,python,python-2.7,kivy,mqtt,paho,Python,Python 2.7,Kivy,Mqtt,Paho,我将Kivy1.11.0与python 2.7.15结合使用 #-*- coding: utf-8 -*- import paho.mqtt.client as mqtt from kivy.app import App from kivy.uix.screenmanager import ScreenManager, Screen from kivy.uix.image import Image from kivy.lang import Builder Builder.load_string

我将Kivy1.11.0与python 2.7.15结合使用

#-*- coding: utf-8 -*-
import paho.mqtt.client as mqtt
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.image import Image
from kivy.lang import Builder
Builder.load_string("""
<InitScreen>:
    AnchorLayout:
        anchor_x:"center"
        anchor_y:"center"
        Label:
            text:"init"
<WaitScreen>:
    Image:
        id:charactor
        pos_hint:{'center_x':.5,'y':0 }
        size_hint:1,1
        source:'./wait1.png'
""")

class Charactor(Image):
    pass
class InitScreen(Screen):
    pass
class WaitScreen(Screen):
    def __init__(self, **kwargs):
        super(WaitScreen, self).__init__(**kwargs)


class View(App):
    sm = ScreenManager()
    cli = mqtt.Client(protocol=mqtt.MQTTv311)
    def __init__(self, **kwargs):
        super(View, self).__init__(**kwargs)

    def build(self):
        self.sm.add_widget(InitScreen(name='init'))
        self.sm.current='init'
        return self.sm

    def on_start(self):
        self.cli.on_connect = self.on_connect
        self.cli.on_message = self.on_message
        self.cli.connect('localhost', port=1883, keepalive=60)
        self.cli.loop_start()

    def on_connect(self,client, userdata, flags, respons_code):
        print('status {0}'.format(respons_code))
        client.subscribe('get/test')

    def on_message(self,client, userdata, msg):
        self.changeScreen()

    def changeScreen(self,**kwargs):
        self.sm.add_widget(WaitScreen(name='wait'))
        self.sm.current='wait'

if __name__ == '__main__':
    View().run()
我想我发现了错误的原因 有形象。 打开_消息加载图像源时,发生错误 我认为paho.mqtt callbackon_message,on_connect)值得怀疑

因为当self.changeScreen处于 def on_启动,def生成,未发生错误

class View(App):
    sm = ScreenManager()
    cli = mqtt.Client(protocol=mqtt.MQTTv311)
    waitflag = False
    def __init__(self, **kwargs):
        super(View, self).__init__(**kwargs)

    def build(self):
        self.sm.add_widget(InitScreen(name='init'))
        self.sm.current='init'
        return self.sm

    def on_start(self):
        self.cli.on_connect = self.on_connect
        self.cli.on_message = self.on_message
        self.cli.connect('localhost', port=1883, keepalive=60)
        self.cli.loop_start()
        Clock.schedule_interval(self.changeScreen, 1) 

    def on_connect(self,client, userdata, flags, respons_code):
        print('status {0}'.format(respons_code))
        client.subscribe('get/test')

    def on_message(self,client, userdata, msg):
        self.waitflag = True

    def changeScreen(self,dt):
        if self.waitflag:
            self.sm.add_widget(WaitScreen(name='wait'))
            self.sm.current='wait'
            self.waitflag = False
下面的代码是错误并没有发生

class View(App):
    sm = ScreenManager()
    cli = mqtt.Client(protocol=mqtt.MQTTv311)
    waitflag = False
    def __init__(self, **kwargs):
        super(View, self).__init__(**kwargs)

    def build(self):
        self.sm.add_widget(InitScreen(name='init'))
        self.sm.current='init'
        return self.sm

    def on_start(self):
        self.cli.on_connect = self.on_connect
        self.cli.on_message = self.on_message
        self.cli.connect('localhost', port=1883, keepalive=60)
        self.cli.loop_start()
        Clock.schedule_interval(self.changeScreen, 1) 

    def on_connect(self,client, userdata, flags, respons_code):
        print('status {0}'.format(respons_code))
        client.subscribe('get/test')

    def on_message(self,client, userdata, msg):
        self.waitflag = True

    def changeScreen(self,dt):
        if self.waitflag:
            self.sm.add_widget(WaitScreen(name='wait'))
            self.sm.current='wait'
            self.waitflag = False
但这段代码感觉很糟糕。因为若WaitScreen不使用图像源,则不会发生错误

class View(App):
    sm = ScreenManager()
    cli = mqtt.Client(protocol=mqtt.MQTTv311)
    waitflag = False
    def __init__(self, **kwargs):
        super(View, self).__init__(**kwargs)

    def build(self):
        self.sm.add_widget(InitScreen(name='init'))
        self.sm.current='init'
        return self.sm

    def on_start(self):
        self.cli.on_connect = self.on_connect
        self.cli.on_message = self.on_message
        self.cli.connect('localhost', port=1883, keepalive=60)
        self.cli.loop_start()
        Clock.schedule_interval(self.changeScreen, 1) 

    def on_connect(self,client, userdata, flags, respons_code):
        print('status {0}'.format(respons_code))
        client.subscribe('get/test')

    def on_message(self,client, userdata, msg):
        self.waitflag = True

    def changeScreen(self,dt):
        if self.waitflag:
            self.sm.add_widget(WaitScreen(name='wait'))
            self.sm.current='wait'
            self.waitflag = False
请告诉我如何避免错误。
我想用上面的代码解决这个问题

from kivy.clock import mainthread

这就是问题所在-SIGSEGV分段错误 根本原因是加载映像,即应用程序正在等待映像加载

笔记 用AsyncImage替换映像将防止应用程序等待映像加载。但在加载4到5个图像/WaitScreen后,它将崩溃,IndexError:list索引超出范围

解决方案 在Python脚本中手动调用Paho MQTT循环方法。 添加了NumericProperty类型的编号,因为屏幕名称在ScreenManager中必须是唯一的。 有关详细信息,请参阅代码段、示例和输出。在这些示例中,我们使用了一个在线代理,如iot.eclipse.org上的代理

一小条 在ScreenManager中必须唯一的屏幕名称。 这是ScreenManager.current使用的名称

name是StringProperty,默认为“”

实例 main.py 输出
你有两次发布相同的代码吗?我不愿意为了确保这一点而加以区分。请澄清或编辑您的问题。uppper代码不是时钟,下面的代码是使用时钟解释更改,而不是张贴几十行相同的行。请澄清“怀疑”和“感觉不好”这两个词——这实际上与感觉无关。@3tori-port=1883或port=1883这实际上并不能解释你改变了什么,也不能解释为什么它解决了问题。请添加更多上下文,然后接受您自己的答案。
def on_start(self):
    self.number = 0
    self.cli = mqtt.Client(protocol=mqtt.MQTTv311)
    self.cli.on_connect = self.on_connect
    self.cli.on_message = self.on_message
    self.cli.connect("iot.eclipse.org", port=1883, keepalive=60)
    Clock.schedule_interval(self.loop, 0.5)    # call loop every 0.5 seconds

def loop(self, dt):
    # manually call the Paho MQTT loop() method
    self.cli.loop(0.1)  # blocks for 100 ms
name
# -*- coding: utf-8 -*-
import paho.mqtt.client as mqtt

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.image import Image
from kivy.lang import Builder
from kivy.properties import NumericProperty
from kivy.clock import Clock

Builder.load_string("""
<InitScreen>:
    AnchorLayout:
        anchor_x:"center"
        anchor_y:"center"
        Label:
            text:"init"

<WaitScreen>:
    Image:
        id: charactor
        pos_hint: {'center_x':.5, 'y':0}
        size_hint: 1, 1
        source: './wait.jpeg'
""")


class Charactor(Image):
    pass


class InitScreen(Screen):
    pass


class WaitScreen(Screen):
    pass


class View(App):

    def build(self):
        self.number = NumericProperty(0)
        self.sm = ScreenManager()
        self.sm.add_widget(InitScreen(name='init'))
        return self.sm

    def on_start(self):
        self.number = 0
        self.cli = mqtt.Client(protocol=mqtt.MQTTv311)
        self.cli.on_connect = self.on_connect
        self.cli.on_message = self.on_message
        self.cli.connect("iot.eclipse.org", port=1883, keepalive=60)
        Clock.schedule_interval(self.loop, 0.5)   # call loop every 0.5 seconds

    def loop(self, dt):
        # manually call the Paho MQTT loop() method
        self.cli.loop(0.1)  # blocks for 100 ms

    def on_connect(self, client, userdata, flags, response_code):
        print("\non_connect:")
        print("\tclient={0}, userdata={1}, flags={2}, response_code={3}".format(client, userdata, flags, response_code))
        client.subscribe("$SYS/#")

    def on_message(self, client, userdata, msg):
        print("\non_message:")
        print("\tclient={0}, userdata={1}, msg={2}".format(client, userdata, msg))
        print("\tmsg.topic={0}, msg.payload={1}".format(msg.topic, msg.payload))
        self.changeScreen()
        self.number += 1

    def changeScreen(self):
        print("\nchangeScreen:")
        print("\tnumber={}".format(self.number))
        screen_name = 'wait{}'.format(self.number)
        print("\tscreen_name={}".format(screen_name))

        self.sm.add_widget(WaitScreen(name=screen_name))
        self.sm.current = screen_name

    def on_stop(self):
        # stop the loop before exit
        self.cli.loop_stop()


if __name__ == '__main__':
    View().run()