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 コンパイルし直し・・・)
結果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を前に入れることです。
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
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/07/18 00:10
2018/07/18 04:52
2018/07/18 06:40
2018/07/18 07:56
2018/07/18 08:42
2018/07/18 09:27 編集