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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Python 2.7

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

Python

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

MQTT

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

Q&A

解決済

1回答

2688閲覧

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

BlueBits

総合スコア57

Python 2.7

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

Python

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

MQTT

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

1グッド

0クリップ

投稿2018/07/17 13:06

編集2018/07/18 09:26

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

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

プログラムの目的

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

発生内容

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

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

python

1#-*- coding: utf-8 -*- 2import paho.mqtt.client as mqtt 3from kivy.app import App 4from kivy.uix.screenmanager import ScreenManager, Screen 5from kivy.uix.image import Image 6from kivy.lang import Builder 7Builder.load_string(""" 8<InitScreen>: 9 AnchorLayout: 10 anchor_x:"center" 11 anchor_y:"center" 12 Label: 13 text:"init" 14<WaitScreen>: 15 Image: 16 id:charactor 17 pos_hint:{'center_x':.5,'y':0 } 18 size_hint:1,1 19 source:'./wait1.png' 20""") 21 22class Charactor(Image): 23 pass 24class InitScreen(Screen): 25 pass 26class WaitScreen(Screen): 27 def __init__(self, **kwargs): 28 super(WaitScreen, self).__init__(**kwargs) 29 30 31class View(App): 32 sm = ScreenManager() 33 cli = mqtt.Client(protocol=mqtt.MQTTv311) 34 def __init__(self, **kwargs): 35 super(View, self).__init__(**kwargs) 36 37 def build(self): 38 self.sm.add_widget(InitScreen(name='init')) 39 self.sm.current='init' 40 return self.sm 41 42 def on_start(self): 43 self.cli.on_connect = self.on_connect 44 self.cli.on_message = self.on_message 45 self.cli.connect('localhost', port='1883', keepalive=60) 46 self.cli.loop_start() 47 48 def on_connect(self,client, userdata, flags, respons_code): 49 print('status {0}'.format(respons_code)) 50 client.subscribe('get/test') 51 52 def on_message(self,client, userdata, msg): 53 self.changeScreen() 54 55 def changeScreen(self,**kwargs): 56 self.sm.add_widget(WaitScreen(name='wait')) 57 self.sm.current='wait' 58 59if __name__ == '__main__': 60 View().run() 61

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

  • 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

python

1# -*- coding: utf-8 -*- 2import paho.mqtt.client as mqtt 3from kivy.app import App 4from kivy.uix.screenmanager import ScreenManager, Screen 5from kivy.lang import Builder 6from kivy.clock import mainthread 7 8Builder.load_string(""" 9<InitScreen>: 10 AnchorLayout: 11 anchor_x:"center" 12 anchor_y:"center" 13 Label: 14 text:"init" 15<WaitScreen>: 16 Image: 17 id:charactor 18 pos_hint:{'center_x':.5,'y':0 } 19 size_hint:1,1 20 source:'./wait3.png' 21""") 22 23 24class InitScreen(Screen): 25 pass 26 27class WaitScreen(Screen): 28 pass 29 30class View(App): 31 def __init__(self, **kwargs): 32 global sm 33 super(View, self).__init__(**kwargs) 34 sm = ScreenManager() 35 36 def build(self): 37 sm.switch_to(InitScreen(name='init')) 38 return sm 39 40 def on_start(self): 41 def on_connect(client, userdata, flags, respons_code): 42 cli.subscribe('get/test') 43 44 @mainthread 45 def on_message(client, userdata, msg): 46 print sm.current 47 io = msg.payload.decode("utf-8") 48 print(msg.topic + ' ' + io) 49 if sm.current != io: 50 if io == 'wait': 51 sm.switch_to(WaitScreen(name='wait')) 52 global cli 53 cli = mqtt.Client(protocol=mqtt.MQTTv311) 54 cli.on_connect = on_connect 55 cli.on_message = on_message 56 cli.connect('localhost', port=1883, keepalive=60) 57 cli.loop_start() 58 59 60if __name__ == '__main__': 61 View().run() 62
gottadiveintopy👍を押しています

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

python

1 def changeScreen(self,**kwargs): 2 self.sm.add_widget(WaitScreen(name='wait')) 3 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/17 23:23

編集2018/07/18 07:25
gottadiveintopy

総合スコア736

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

BlueBits

2018/07/18 00:10

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

2018/07/18 04: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側でもエラーは発生しませんでしたが、画像は表示されませんでした。
BlueBits

2018/07/18 06:40

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

2018/07/18 07:56

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

2018/07/18 08:42

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

2018/07/18 09:27 編集

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問