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

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

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

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

while

Whileは多くの言語で使われるコントロール構造であり、特定の条件が満たされる限り一連の命令を繰り返し実行します。

スレッドセーフ

マルチスレッド環境において、複数のスレッド上で常に正常に実行する事が可能なコードを、スレッドセーフなコードと呼びます。

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

Python

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

Q&A

解決済

2回答

4430閲覧

wxpythonにてフラグによって動画再生や切り替えを行う方法。

dendenmushi

総合スコア98

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

while

Whileは多くの言語で使われるコントロール構造であり、特定の条件が満たされる限り一連の命令を繰り返し実行します。

スレッドセーフ

マルチスレッド環境において、複数のスレッド上で常に正常に実行する事が可能なコードを、スレッドセーフなコードと呼びます。

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

Python

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

0グッド

0クリップ

投稿2020/04/27 17:21

編集2020/04/27 17:23

以前質問させて頂いたあとの別のやりかたの質問をさせて下さい。
https://teratail.com/questions/256690#reply-369648

前提・実現したいこと

wxpythonでgif動画を再生するデスクトップアプリを作っています。
10秒後(不確定な第三者の反応に応じた後<例えばメール受信等々>)にgif動画を切り替えたい。

Architectureと発生している問題・エラーメッセージ

<方法1>
wxpythonのmain部分に動画再生メソッドと、チェック機能(例えばwhileで常に第三者の反応をチェックするメソッド)をmainに一緒に置いてしまうと、main側の動画再生ができませんでした。

結果
イメージ説明
以下ソースコードです。

python

1# coding:utf-8 2import os 3import sys 4import time 5import cv2 6import numpy as np 7import wx.adv 8import time 9 10import os 11import wx 12class MainWindow(wx.Frame): 13 # def __init__(self): 14 def __init__(self, parent, id, title): 15 wx.Frame.__init__(self, parent, id, title, size=(700, 600)) 16 17 self.ctrl = wx.adv.AnimationCtrl(self) 18 self.ctrl.Stop() 19 20 from glob import glob 21 from itertools import cycle 22 from functools import partial 23 24 def showNextImage(): 25 filepath = 'someiyoshino1.gif' 26 print(filepath) 27 self.ctrl.SetAnimation(wx.adv.Animation(filepath)) 28 self.ctrl.Play() 29 30 def showNextImage2(): 31 filepath = 'someiyoshino2.gif' 32 print(filepath) 33 self.ctrl.SetAnimation(wx.adv.Animation(filepath)) 34 self.ctrl.Play() 35 36 count = 0 37 # 第三者アクション ボタン押下などではなく(メール受信など予測が難しいタイミング等) 38 # フラグが立った時に動画を再生や切り替えを行いたい。 39 while True: 40 count += 1 41 print(count) 42 if(count == 10): 43 showNextImage2() 44 time.sleep(1) 45 46 47 48from multiprocessing import Process, Value 49import time 50 51def main(a:Value): 52 print("mainスタート") 53 app = wx.App() 54 win = MainWindow(None, wx.ID_ANY, 'TOTO') 55 win.Centre() 56 win.Show() 57 app.MainLoop() 58 59def func1(a: Value): 60 print("[func1]スタート") 61 while True: 62 if(a.Value == 1): 63 wx.CallLater(1000*1, self.showNextImage) 64 65 66if __name__ == "__main__": 67 68 a = Value('d', 0) 69 70 func0_proc = Process(target=main, args=(a,)) 71 func1_proc = Process(target=func1, args=(a,)) 72 73 func0_proc.start() 74 func1_proc.start() 75 76 func0_proc.join() 77 func1_proc.join() 78 79 print(a.value)

<方法2>
あらかじめ同じメモリ内にa.Valueの変数を作り、wxpythonのmain部分に動画再生メソッドを置き、チェック機能(例えばwhileで常に第三者の反応をチェックするメソッド)を別のスレッドにして並行稼働してチェックし、一定条件でa.Valueを変化させ、mainスレッドでa.Valueの変化を察知してCallLaterで同main内の動画再生メソッド呼び出しを行いましたが、実行されませんでした。

結果
イメージ説明

ソースコードは以下です。

python

1# coding:utf-8 2import os 3import sys 4import time 5import cv2 6import numpy as np 7import wx.adv 8import time 9import os 10import wx 11choose_text_h5 = "" 12 13class MainWindow(wx.Frame): 14 # def __init__(self): 15 def __init__(self, parent, id, title): 16 wx.Frame.__init__(self, parent, id, title, size=(700, 600)) 17 18 self.ctrl = wx.adv.AnimationCtrl(self) 19 self.ctrl.Stop() 20 21 from glob import glob 22 from itertools import cycle 23 from functools import partial 24 25 def showNextImage(): 26 filepath = 'someiyoshino1.gif' 27 print(filepath) 28 self.ctrl.SetAnimation(wx.adv.Animation(filepath)) 29 self.ctrl.Play() 30 31 def showNextImage2(): 32 filepath = 'someiyoshino2.gif' 33 print(filepath) 34 self.ctrl.SetAnimation(wx.adv.Animation(filepath)) 35 self.ctrl.Play() 36 37 if(a.Value == 1): 38 wx.CallLater(1000*1, showNextImage) 39 40 41from multiprocessing import Process, Value 42import time 43 44def main(a:Value): 45 print("mainスタート") 46 # app = wx.App(False) 47 # Main().Show(True) 48 # app.MainLoop() 49 app = wx.App() 50 win = MainWindow(None, wx.ID_ANY, 'TOTO') 51 win.Centre() 52 win.Show() 53 app.MainLoop() 54 55def func1(a: Value): 56 print("[func1]スタート") 57 58 count = 0 59 while True: 60 count += 1 61 print(count) 62 if(count == 10): 63 a.Value = 1 64 time.sleep(1) 65 print(a.value) 66 67def func2(self, a: Value): 68 print("[func2]スタート") 69 # while True: 70 # if(a.Value == 1): 71 # wx.CallLater(1000*1, self.showNextImage) 72 73if __name__ == "__main__": 74 75 a = Value('d', 0) 76 77 func0_proc = Process(target=main, args=(a,)) 78 func1_proc = Process(target=func1, args=(a,)) 79 func2_proc = Process(target=func2, args=(a,)) 80 81 func0_proc.start() 82 func1_proc.start() 83 func2_proc.start() 84 85 func0_proc.join() 86 func1_proc.join() 87 func2_proc.join() 88 print(a.value)

<方法3>
あらかじめ同じメモリ内にa.Valueの変数を作り、wxpythonのmain部分に動画再生メソッドを置き、チェック機能(例えばwhileで常に第三者の反応をチェックするメソッド)を別のスレッドにして並行稼働してチェックし、一定条件でa.Valueを変化させ、3つ目のスレッドでa.Valueの変化を察知してmain側に対してCallLaterでメソッド呼び出しを行いましたが、実行されませんでした。

結果
イメージ説明
ソースコードは以下です。

python

1# coding:utf-8 2import os 3import sys 4import time 5import cv2 6import numpy as np 7import wx.adv 8import time 9import os 10import wx 11choose_text_h5 = "" 12 13class MainWindow(wx.Frame): 14 def __init__(self, parent, id, title): 15 wx.Frame.__init__(self, parent, id, title, size=(700, 600)) 16 17 self.ctrl = wx.adv.AnimationCtrl(self) 18 self.ctrl.Stop() 19 20 from glob import glob 21 from itertools import cycle 22 from functools import partial 23 24 self.MainPanel = wx.Panel(self, size=(1300, 900))#メイン画面の大きさ 25 26 def showNextImage(): 27 filepath = 'someiyoshino1.gif' 28 print(filepath) 29 self.ctrl.SetAnimation(wx.adv.Animation(filepath)) 30 self.ctrl.Play() 31 32 def showNextImage2(): 33 filepath = 'someiyoshino2.gif' 34 print(filepath) 35 self.ctrl.SetAnimation(wx.adv.Animation(filepath)) 36 self.ctrl.Play() 37 38from multiprocessing import Process, Value 39import time 40 41def main(): 42 print("mainスタート") 43 # app = wx.App(False) 44 # Main().Show(True) 45 # app.MainLoop() 46 app = wx.App() 47 win = MainWindow(None, wx.ID_ANY, 'TOTO') 48 win.Centre() 49 win.Show() 50 app.MainLoop() 51 52def func1(self): 53 print("[func1]スタート") 54 55 count = 0 56 while True: 57 count += 1 58 print(count) 59 if(count == 10): 60 wx.CallLater(1000*1, self.showNextImage) 61 time.sleep(1) 62 63if __name__ == "__main__": 64 65 # a = Value('d', 0) 66 67 func0_proc = Process(target=main) 68 func1_proc = Process(target=func1) 69 70 func0_proc.start() 71 func1_proc.start() 72 73 func0_proc.join() 74 func1_proc.join() 75 print(a.value)

<方法4>

動画再生側をmain側ではなく、別のメソッドとして外部に配置する方法を試みようとしましたが、外部メソッド実行じたいができませんでした。

結果
イメージ説明

python

1import wx 2import wx.adv 3 4from glob import glob 5from itertools import cycle 6from functools import partial 7 8def showNextImage(): 9 filepath = 'someiyoshino1.gif' 10 print(filepath) 11 wx.adv.AnimationCtrl.SetAnimation(wx.adv.Animation(filepath)) 12 wx.adv.AnimationCtrl.Play() 13showNextImage() 14

方法1~4まで全て試したのですが、うまくいきませんでした。
任意のフラグによって動画を差し替えたり再生したりなどはどのように行えばよいのでしょうか。
よろしくお願い致します。

補足情報(FW/ツールのバージョンなど)

win10
python3.7
wxpython

参考サイト

https://teratail.com/questions/158458
https://teratail.com/questions/233764
https://qiita.com/wikipediia/items/2919362de582a7d8de9e
https://www.python-beginners.com/entry/20191125/1574687207
https://qiita.com/asakbiz/items/5a34cae7b6c00c87a7e6
https://dev.classmethod.jp/articles/python-asyncio/
https://www.rhoboro.com/2019/02/09/coroutine-abstract.html
https://qiita.com/satsukiya/items/f7a3c7fdae566ed96306
https://www.yoheim.net/blog.php?q=20170601

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

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

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

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

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

guest

回答2

0

ベストアンサー

PostEvent を用いて通知する方法です。

python

1 2import os 3import sys 4import time 5from threading import Thread 6 7import wx 8from wx.adv import Animation, AnimationCtrl 9from wx.lib.newevent import NewEvent 10 11UpdateImageEvent, EVT_UPDATE_IMAGE = NewEvent() 12 13 14class CountTimer(Thread): 15 daemon = True 16 17 def __init__(self, win): 18 super().__init__() 19 20 # イベント通知対象のウィジェット。(MainWindow) 21 self.win = win 22 23 # 次の画像ファイルを所得する関数 (仮: カレントディレクトリの gif ファイルが対象) 24 from glob import glob 25 from itertools import cycle 26 from functools import partial 27 self.nextImageFile = partial(next, cycle(glob("*.gif"))) 28 29 def run(self): 30 num = 0 31 while True: 32 num += 1 33 if num % 10 == 0: # 剰余で十秒毎を判別 34 35 # 次に表示する画像ファイル 36 filepath = self.nextImageFile() 37 38 # イベント通知する為、引数となるイベントオブジェクトを作成 39 event = UpdateImageEvent(filepath=filepath) 40 41 # 通知 (MainLoopのキューにイベントを入れる) 42 wx.PostEvent(self.win, event) 43 44 del event, filepath 45 time.sleep(1) 46 47 48class MainWindow(wx.Frame): 49 def __init__(self, parent=None, ID=wx.ID_ANY, title="", *args, **kw): 50 super().__init__(parent, ID, title, *args, **kw) 51 self.animeCtrl = AnimationCtrl(self) 52 53 # イベントとイベント通知受信時に呼び出されるコールバック関数の結び付け 54 self.Bind(EVT_UPDATE_IMAGE, self.OnUpdateImage) 55 56 def OnUpdateImage(self, event): 57 # PostEvent での通知により *メインスレッドで* 実行される 58 print("OnUpdateImage", event.filepath) 59 self.SetImageFile(event.filepath) 60 61 def SetImageFile(self, filepath): 62 # 画像・動画を変更し再生する 63 assert os.path.isfile(filepath) 64 self.animeCtrl.SetAnimation(Animation(filepath)) 65 self.animeCtrl.Play() 66 67 68def main(): 69 app = wx.App() 70 win = MainWindow() 71 win.SetSize(400, 400) 72 win.Centre() 73 win.Show() 74 75 thread = CountTimer(win) 76 thread.start() 77 78 app.MainLoop() 79 80 81if __name__ == '__main__': 82 main()

数値のカウントの方法について、
Pythonの数値型は多倍長なので、桁溢れの心配はないとはいえ
気になる部分なので、改善案。追記: インデントが深くならないように再度修正。

カウント自体の処理と、カウント毎の処理の分離もできます。

python

1class CountTimer(Thread): 2 daemon = True 3 4 # 省略 5 6 def onCountInterval(self): 7 # 次に表示する画像ファイル 8 filepath = self.nextImageFile() 9 10 # イベント通知する為、引数となるイベントオブジェクトを作成 11 event = UpdateImageEvent(filepath=filepath) 12 13 # 通知 (MainLoopのキューにイベントを入れる) 14 wx.PostEvent(self.win, event) 15 16 def run(self, count=10, interval=1): 17 while True: 18 for _ in range(count): 19 time.sleep(interval) 20 else: 21 self.onCountInterval() 22

投稿2020/04/27 22:56

編集2020/04/28 16:37
teamikl

総合スコア8664

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

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

dendenmushi

2020/04/28 09:35

解決法も完璧で説明も丁寧で本当に感謝です。私の知らない知識が詰まっていまして大変に勉強になりました。NewEventというのは初めて見ました。 UpdateImageEvent, EVT_UPDATE_IMAGE = NewEvent() ここの部分はUpdateImageEventとEVT_UPDATE_IMAGEを繋げているという解釈でいいのでしょうか。 そうでなければ下の⑥から⑦に指令が伝搬するコードの繋がりができなくなってしまうと解釈しています。 ①win = MainWindow() ↓ ② thread = CountTimer(win) #Mainwindowのインスタンスを引数に入れて thread.Start() # スタートさせて ↓ ③ self.target = win # 代入して ↓ ④ run # これは自動で実行されるのですね… ↓ ⑤ event = UpdateImageEvent(filepath=filepath) #UpdateImageEventのイベントオブジェクト作成 ↓ ⑥ wx.PostEvent(self.target, event) # MainWindowでUpdateImageEventを実行指令 ↓ ⑦ self.Bind(EVT_UPDATE_IMAGE, self.OnUpdateImage) # bindされたOndataImage実行指令 ↓ ⑧ self.SetImageFile(event.filepath) #SetImageFile実行指令 ↓ ⑨ self.animeCtrl.Play() # 再生開始
teamikl

2020/04/28 11:39

> ここの部分はUpdateImageEventとEVT_UPDATE_IMAGEを繋げているという解釈でいいのでしょうか。 概ねその理解で合ってます。 > self.target = win # 代入して 釈明なのですが。ここは、変数の命名 "target" が紛らわしい名前でした。 (実行に支障はありません) wxのイベントを送るターゲットとして付けたつもりでしたが、 pythonのThread も target という引数を持ちます。 run()メソッドをオーバーライドしない場合は、 コンストラクタに実行する関数をtargetとして渡すことができます。 > (4) run # これは自動で実行されるのですね… Python のThread クラスの仕組みでそうなってます。 この辺りはオブジェクト指向のデメリット部分で、 中の仕組みを知らないと、ここでコードの流れが追えなくなるのが欠点。 明示的に Thread のtarget引数で関数を渡した方が良い場合もあります。 https://docs.python.org/ja/3/library/threading.html ---- 一点だけ、 コードが実際に実行される順序は、(7) は事前準備なのでこの順序ではなく (6) PostEvent で イベントキューに追加 -> (メインスレッド側で) MainLoop() 各イベント処理の中で -> (8) という流れになります。 (コードを追う流れとしては正解です。実行順とは違うというだけ) 意識して見てほしいのは、 それぞれのコードがどのスレッドで実行されているかという点。 (threading.current_threadやget_identを表示させて確かめて見て下さい) ==== 最後に参考リソース - 非同期プログラムでマルチスレッドが動かない場合と対処方法 https://rightcode.co.jp/blog/information-technology/python-asynchronous-program-multithread-does-not-work-approach なぜマルチスレッドだとうまくいかないかの説明と、 別アプローチの方法ですが、 「マルチスレッドで画像を動画として再生してみる」をタイマーを使って実装されてます。 - 公式wikiより (英語) NewEventやキューを使ったスレッド間通信のサンプルコード https://wiki.wxpython.org/LongRunningTasks この後良く問題になる事で、終了時にスレッドを安全に(エラーを出さず) アプリケーションを終了させるにはどうするかという事があります。 説明を省いてしまったのですが、 上のコードではdaemon=True として、メインスレッド終了時に 同時に強制終了しています。が、ネットワーク等にアクセスしてる場合等は daemon=Trueにして強制終了にはせず、正規の手続きで終了した方が良いことも有ります。 以前のスレッドのコードにはあった、self.keepGoing 等のフラグ判断で スレッドのループを抜けたりする処理ですね。 wikiにあるサンプルコードでは "abort" として実装されてるので、 必要になったら参考にして見て下さい。
dendenmushi

2020/04/28 13:08

daemon=Trueも初めてでした。非常に奥深いのですね…大変勉強になりました。ありがとうございました。またよろしくお願い致します。
guest

0

<方法1>

wxpythonのmain部分に動画再生メソッドと、チェック機能(例えばwhileで常に第三者の反応をチェックするメソッド)をmainに一緒に置いてしまうと、main側の動画再生ができませんでした。

wx等のGUIではマウスイベント等を処理する為の MainLoop を持ちます。
その為メインスレッドでループを組んでしまうと、他のイベントが処理されなくなります。

各種イベントで呼ばれるコールバックは別スレッドで実行されてるわけではなく、
イベント処理のループ → 自分で定義したイベント → イベント処理のループ という流れです。

ループ内で wx.Yield() や wx.YieldIfNeeded() を呼ぶことで一時的には回避できますが、
根本的な問題解決にはなりません。

上記のコードであれば MainWindow のコンストラクタ内で止ってしまうので、
win.Show() 等が呼ばれません。

この方法(メインスレッドでループを実行したい)を取りたい場合は、MainLoop()を使わずに、
「非同期プログラミング」という手法を取ります。wxではあまり事例がない上に、
コードも設計から大幅な変更を要求される為、詳細な説明は見送ります。


<方法2>

あらかじめ同じメモリ内にa.Valueの変数を作り、

  • 見た感じ、a.value と a.Value の typoが?
  • MainWindow に変数 a が渡っていない
  • func2 呼び出し時の引数不一致。(ここはself不要)

但し、方法自体にまだ課題があり、
a.value == 1 になった時に切り替わりますが、
a.value == 1 の時に常に画像が切り替わり続けます。(剰余で判断したほうが良いのでは)

コードの不要な部分を省き、エラーのみ修整したので動作を確かめて見て下さい。

python

1# coding:utf-8 2import os 3import sys 4import time 5import wx 6import wx.adv 7from multiprocessing import Process, Value 8 9class MainWindow(wx.Frame): 10 # def __init__(self): 11 def __init__(self, parent, id, title, a): 12 wx.Frame.__init__(self, parent, id, title, size=(700, 600)) 13 14 self.ctrl = wx.adv.AnimationCtrl(self) 15 self.ctrl.Stop() 16 17 self.a = a 18 self.watchValueChanged() 19 20 from glob import glob 21 from functools import partial 22 from itertools import cycle 23 self.nextImageFile = partial(next, cycle(glob("*.gif"))) 24 25 def showNextImage(self): 26 filepath = self.nextImageFile() # ここの戻り値を毎回変化させる。 27 print(filepath) 28 self.ctrl.SetAnimation(wx.adv.Animation(filepath)) 29 self.ctrl.Play() 30 31 def watchValueChanged(self): 32 if(self.a.value == 1): 33 wx.CallAfter(self.showNextImage) 34 wx.CallLater(1000*10, self.watchValueChanged) 35 36 37def main(a:Value): 38 print("mainスタート") 39 app = wx.App() 40 win = MainWindow(None, wx.ID_ANY, 'TOTO', a) 41 win.Centre() 42 win.Show() 43 app.MainLoop() 44 45def func1(a: Value): 46 print("[func1]スタート") 47 48 count = 0 49 while True: 50 count += 1 51 print(count) 52 if(count == 10): 53 a.value = 1 54 time.sleep(1) 55 print(a.value) 56 57 58if __name__ == "__main__": 59 a = Value('d', 0) 60 61 func0_proc = Process(target=main, args=(a,)) 62 func1_proc = Process(target=func1, args=(a,)) 63 64 func0_proc.start() 65 func1_proc.start() 66 67 func0_proc.join() 68 func1_proc.join() 69 print(a.value)

<方法3>

あらかじめ同じメモリ内にa.Valueの変数を作り、wxpythonのmain部分に動画再生メソッドを置き、
3つ目のスレッドでa.Valueの変化を察知してmain側に対してCallLaterでメソッド呼び出しを行いましたが、実行されませんでした。

これは、「スレッド」ではなく「プロセス」であるためです。

もう一点、showNextImage関数は、内部で定義された関数の為、
外から呼び出せるようにはなっていません。

この場合は、mainはスレッドにする必要はなく、
秒数カウントのみを別スレッドにして、MainWindowのインスタンスを渡します。

# coding:utf-8 import os import sys import time from threading import Thread import wx import wx.adv class MainWindow(wx.Frame): def __init__(self, parent, id, title): wx.Frame.__init__(self, parent, id, title, size=(700, 600)) self.ctrl = wx.adv.AnimationCtrl(self) self.ctrl.Stop() self.MainPanel = wx.Panel(self, size=(1300, 900))#メイン画面の大きさ from glob import glob from functools import partial from itertools import cycle self.nextImageFile = partial(next, cycle(glob("*.gif"))) def showNextImage(self): filepath = self.nextImageFile() print(filepath) self.ctrl.SetAnimation(wx.adv.Animation(filepath)) wx.CallAfter(self.ctrl.Play) def func1(win): print("[func1]スタート") count = 1 while True: count += 1 print(count) if(count % 10 == 0): # ※ 10秒毎に切り替わるように剰余で判断 win.showNextImage() time.sleep(1) if __name__ == "__main__": app = wx.App() win = MainWindow(None, wx.ID_ANY, 'TOTO') thread = Thread(target=func1, args=(win,)) thread.start() win.Centre() win.Show() app.MainLoop()

※ この例では、Play() のみを CallAfter で呼び出すようにしました。
Set 系のメソッドは直接描画に関与せず、
外部スレッド側でデータ更新 ⇒ メインスレッドで描画という流れになります。
ただし、ロックはしてないので別スレッドから上書きされる可能性はあります。

ここで一点訂正なのですが、以前、スレッドからCallLaterを使いと言ってた部分、
wxではスレッドからはタイマーを作成できませんでした。(他のGUIライブラリと混同していた)

可能ならCallLater,CallAfter等のタイマーではなく、
以前のコードで使われていた PostEvent を使い通知する方がより安全です。


<方法4>

動画再生側をmain側ではなく、別のメソッドとして外部に配置する方法を試みようとしましたが、外部メソッド実行じたいができませんでした。

これは簡単な例を使って説明します。
(他にも方法2, 3と同様の問題も有りますが、上で説明した通りです)

Python のクラスメソッドとインスタンスメソッドとの違いの為、
引数が正しく渡ってません。

python

1 2class MyClass: 3 def __init__(self, value): 4 self.value = value 5 6 def add(self, num): 7 return self.value + num 8 9obj = MyClass(10) 10 11# 通常の呼び出し (インスタンスメソッド経由) 12print(obj.add(20)) # => 30 13 14 15# 直接呼出し (第一引数(self)のインスタンスを明示的に渡す必要があります) 16print(MyClass.add(obj, 20)) # => 30
  • obj.add はインスタンス経由での呼び出し、インスタンスメソッドといって

第一引数のself が自動的に自分自身が束縛されているので、呼び出すときの引数に省略できます。
obj.add(obj, 10) とは書きません。

  • MyClass.add はクラスMyClass に置かれた通常の関数です

通常の関数と同じように呼び出せますが、第一引数の self を明示的に要求します。

インスタンスを要求されますが、
インスタンスがあれば、そもそも通常インスタンスメソッドの呼び出しで良いので、
スコープ問題の解消として、この解決策は適してません。

投稿2020/04/27 21:32

編集2020/04/27 23:31
teamikl

総合スコア8664

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

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

dendenmushi

2020/04/28 10:04 編集

他の方法でもご教授ありがとうございました。teamiklさんの上の回答の方でベストアンサーに選ばせて下さい。もしよろしければまた回答依頼出させて頂けないでしょうか。差し支えなければ相互フォローどうかよろしくお願い致します。この回答は私の宝物です。
teamikl

2020/04/28 10:20

上のコメントは今から読ませてもらいます。 回答依頼という機能があったのですね。 使ったことはなかったのですが、よろしくです。 メール通知は切ってるか開いてないので、 非アクティブ時は気付けない事も有るかもしれないのはご了承ください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問