質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.34%

  • Python

    9279questions

    Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

  • Python 2.7

    1349questions

    Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

  • MQTT

    29questions

    MQTT(Message Queue Telemetry Transport)とは、TCP/IPネットワークで利用可能な通信プロトコルの一つで、IoT/M2M向けに開発された軽量なプロトコルです。ヘッダ部分は最小2バイトと小さく、通信量・CPU負荷・電力消費量などを抑えることができます。

kivy + mqtt on_message時の際の表示エラーの解決方法

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 313

BlueBits

score 41

Fatal Python error: (pygame parachute) Segmentation Fault Abort trap: 6 エラーが発生します。

質問の最後に成功例を掲載いたしました。

 プログラムの目的

ScreenManagerにてmqttから通信がきた場合、Screenを切り替える
その際、通信内容からScreenに表示する画像を決める

 発生内容

 on_messageにて取得後、切り替え操作の際,切り替え後のScreenにImaegeがあると発生する

以下は発生したエラーを切り分けるため、縮小したプログラムです。
mqttで何かしらきたらScreenを切り替えるだけのものです。

#-*- 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()

 エラーが発生しないパターン

  • ImageWidget で 画像がない場合(sourceなしや、ファイルがない場合)
  • ImageWidget がない場合 (Labelの場合切り替えが可能)
  • add_widget(WaitScreen(name='wait'))を、Build内で先に設定

画像を読み込みしようとすると発生するようです。

 追記1 logLevel=trace

エラー発生前のログです。

[TRACE  ] [Lang        ] Found 2 rules for <Screen name='wait'>
[TRACE  ] [Lang        ] Found 1 rules for <kivy.uix.image.Image object at 0x11143c2f0>
[DEBUG  ] [ImageImageIO] Load </img/wait1.png>
[TRACE  ] [Image       ] u'/img/wait1.png', populate to textures (1)
Fatal Python error: (pygame parachute) Segmentation Fault
Abort trap: 6

 追記2 無理やりon_messageで動かした方法

on_message時はフラグ管理だけさせ、Clockでスクリーン変更のフラグチェックをして変更
かなりきな臭いのですがこの場合では想定した動作にはなります。

#-*- 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.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:'./img/wait1.png'
""")

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)
    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

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

 追記3  mqtt(paho.mqtt.client)のコールバック時に発生

コールバックに使用しているon_message(on_connect)のself.changeScreen()を実行するとエラーが質問のエラーが発生します。on_start時は成功しました。

 追記4 pygame->SDL2 への変更

回答頂きました内容にpygameからSDL2への推奨がされているということで変更いたしました。
併せてRaspberryPiにも同様のプログラムを走らせました。

(簡単にSDL2に変更できるかと思ったら想像以上に苦戦していまいました。kivy コンパイルし直し・・・)

https://stackoverflow.com/questions/41819955/how-to-i-get-kivy-1-9-1-or-1-9-2-to-use-sdl2-instead-of-pygame-on-osx-10-12-2

結果1 RaspberryPiの際は、エラー落ちはしないものの表示されません

[INFO   ] [Kivy        ] v1.11.0.dev0, git-df7de20, 20180705
[INFO   ] [Python      ] v2.7.13 (default, Nov 24 2017, 17:33:09) 
[GCC 6.3.0 20170516]
[INFO   ] [Factory     ] 194 symbols loaded
[INFO   ] [Image       ] Providers: img_tex, img_dds, img_sdl2, img_gif (img_pil, img_ffpyplayer ignored)
[INFO   ] [Window      ] Provider: egl_rpi
[INFO   ] [GL          ] Using the "OpenGL ES 2" graphics system
[INFO   ] [GL          ] Backend used <gl>
[INFO   ] [GL          ] OpenGL version <OpenGL ES 2.0>
[INFO   ] [GL          ] OpenGL vendor <Broadcom>
[INFO   ] [GL          ] OpenGL renderer <VideoCore IV HW>
[INFO   ] [GL          ] OpenGL parsed version: 2, 0
[INFO   ] [GL          ] Shading version <OpenGL ES GLSL ES 1.00>
[INFO   ] [GL          ] Texture max size <2048>
[INFO   ] [GL          ] Texture max units <8>
[INFO   ] [Window      ] virtual keyboard not allowed, single mode, not docked
[INFO   ] [Text        ] Provider: sdl2
[INFO   ] [Base        ] Start application main loop
[INFO   ] [GL          ] NPOT texture support is available


結果2 MacbookProの際は、エラー発生で落ちました
ただし内容は、Segmentation fault: 11 になりました。

[INFO   ] [Kivy        ] v1.11.0.dev0, git-0471549, 20180718
[INFO   ] [Python      ] v2.7.15 (default, Jul  3 2018, 14:22:35)
[GCC 4.2.1 Compatible Apple LLVM 9.1.0 (clang-902.0.39.2)]
[INFO   ] [Factory     ] 194 symbols loaded
[INFO   ] [Image       ] Providers: img_tex, img_imageio, img_dds, img_sdl2, img_gif (img_pil, img_ffpyplayer ignored)
[INFO   ] [Window      ] Provider: sdl2
[INFO   ] [GL          ] Using the "OpenGL ES 2" graphics system
[INFO   ] [GL          ] Backend used <gl>
[INFO   ] [GL          ] OpenGL version <2.1 INTEL-10.34.27>
[INFO   ] [GL          ] OpenGL vendor <Intel Inc.>
[INFO   ] [GL          ] OpenGL renderer <Intel(R) Iris(TM) Graphics 6100>
[INFO   ] [GL          ] OpenGL parsed version: 2, 1
[INFO   ] [GL          ] Shading version <1.20>
[INFO   ] [GL          ] Texture max size <16384>
[INFO   ] [GL          ] Texture max units <16>
[INFO   ] [Window      ] auto add sdl2 input provider
[INFO   ] [Window      ] virtual keyboard not allowed, single mode, not docked
[INFO   ] [Text        ] Provider: sdl2
[INFO   ] [Base        ] Start application main loop
[INFO   ] [GL          ] NPOT texture support is available

 追記 成功例1 別スレッドをメインスレッドとしてkivy を操作する

今回のエラー・表示がおかしい理由は、回答にあります別スレッドからの動作が原因でした。
OpenGL関連は別スレッドではダメなそうです。

その解決策として以下の方法がありました。

必要な部分は、from kivy.clock import mainthread
メインスレッドで操作させたい別スレッド(ここではon_message)に@mainthreadを前に入れることです。

https://kivy.org/docs/api-kivy.clock.html

# -*- coding: utf-8 -*-
import paho.mqtt.client as mqtt
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.clock import mainthread

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:'./wait3.png'
""")


class InitScreen(Screen):
    pass

class WaitScreen(Screen):
    pass

class View(App):
    def __init__(self, **kwargs):
        global sm
        super(View, self).__init__(**kwargs)
        sm = ScreenManager()

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

    def on_start(self):
        def on_connect(client, userdata, flags, respons_code):
            cli.subscribe('get/test')

        @mainthread
        def on_message(client, userdata, msg):
            print sm.current
            io = msg.payload.decode("utf-8")
            print(msg.topic + ' ' + io)
            if sm.current != io:
                if io == 'wait':
                    sm.switch_to(WaitScreen(name='wait'))
        global cli
        cli = mqtt.Client(protocol=mqtt.MQTTv311)
        cli.on_connect = on_connect
        cli.on_message = on_message
        cli.connect('localhost', port=1883, keepalive=60)
        cli.loop_start()


if __name__ == '__main__':
    View().run()
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

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

このMethodは多分何度も呼び出されますよね?ScreenManagerの子Screen達に付ける名前は被らない様にしないといけません。このMethodの二度目の呼び出しの時に二つ目のwaitという名前の子Screenを加えようとした事になってErrorになった可能性があります。もし二回目以降の呼び出しで前回のWaitScreenが要らないなら先にremove、要るなら名前が被らない様に変えないといけないです。

Fatal Python error: (pygame parachute) Segmentation Fault Abort trap: 6

pygameは非推奨なのでSDL2を使うべきですよ

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/07/18 09:10

    回答ありがとうございます。スクリーン名重複の場合は、[WARNING] [Multiple screens named "wait"] [<Screen name='wait'>, <Screen name='wait'>]のような形で警告はしますが動作しますので今回の原因とは別と考えいます。
    >pygameは非推奨なのでSDL2
    について、 print os.environ['KIVY_WINDOW'] でにて、sdl2と表示されてたので SDL2で動作していたのかと思いましたが実際はちがうのでしょうか。

    キャンセル

  • 2018/07/18 13:52

    追記:raspberryでも試したところ、エラー環境は pygameでした。raspberryのほうはsdl2
    macbook:
    [INFO ] [Image ] Providers: img_tex, img_imageio, img_dds, img_pygame, img_gif (img_pil, img_ffpyplayer ignored)
    raspberry:
    [INFO ] [Image ] Providers: img_tex, img_dds, img_sdl2, img_gif (img_pil, img_ffpyplayer ignored)

    ただ、raspberry側でもエラーは発生しませんでしたが、画像は表示されませんでした。

    キャンセル

  • 2018/07/18 15:40

    MacBookPro側(pygameになっていた方)もなんとかSDL2に切り替えいたしました。
    (pyenv等使っているためか一筋縄で入らなかったです。)
    結局エラー落ちとなりましたのでご質問に追記という形で掲載いたします。

    キャンセル

  • 2018/07/18 16:56

    分かりやすいErrorが無くてなかなか厳しいですね..

    最後に私が思い付く可能性は、mqttが別にThreadを作っていてそれによってKivyを2つのThreadが同時に触ってしまった です。そう考えると "無理やりon_messageで動かした方法" で上手くいったのも納得できます。この方法だとon_message()内ではKivyに触れていないので。

    キャンセル

  • 2018/07/18 17:42

    mqttはsubscribeのメッセージ待ちのため別スレッドで動作しています。画像なしの場合は動作していたので問題ないのかなと思っていましたが、別スレッド時のImageのファイルアクセス・表示の部分を考えれば解決できそうです。

    キャンセル

  • 2018/07/18 18:15 編集

    解決しました。いただいたコメントがなければわかりませんでした。
    状況としてmacbookpro ,raspberryP3ともに無事表示されました。
    質問に追記という形で成功例を掲載いたします。
    parentの質問も含め改めてありがとうございます。またquiitaの方でも参考にしておりたすかっています。

    キャンセル

同じタグがついた質問を見る

  • Python

    9279questions

    Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

  • Python 2.7

    1349questions

    Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

  • MQTT

    29questions

    MQTT(Message Queue Telemetry Transport)とは、TCP/IPネットワークで利用可能な通信プロトコルの一つで、IoT/M2M向けに開発された軽量なプロトコルです。ヘッダ部分は最小2バイトと小さく、通信量・CPU負荷・電力消費量などを抑えることができます。