友人と私は、Python と PyGame を学び、楽しむために、大規模なプロジェクトに取り組んでいます。基本的には、小さな村の AI シミュレーションです。昼夜のサイクルが必要だったので、NumPy を使用して表面全体の色を変更する便利な方法を見つけました (具体的には、クロスフェード チュートリアル) -http://www.pygame.org/docs/tut/surfarray/SurfarrayIntro.html
コードに実装したところ、動作はしましたが、非常に遅く、1 fps 未満でした。そこで、スレッド化について調べて (最終的には追加したかったので)、キューに関するこのページを見つけました。Python の Queue モジュールについて学ぶ (実行方法)
基本的なシステムを作るのに15分ほどかかりましたが、実行するとすぐにウィンドウが閉じて、
Exception in thread Thread-1 (most likely raised during interpreter shutdown):
編集: 文字通りこれだけです。トレースバックエラーはありません。
何が間違っているのか分かりませんが、何か簡単なことを見落としているのではないかと思います。以下のコードの必要な部分を追加しました。
q_in = Queue.Queue(maxsize=0)
q_out = Queue.Queue(maxsize=0)
def run(): #Here is where the main stuff happens
#There is more here I am just showing the essential parts
while True:
a = abs(abs(world.degree-180)-180)/400.
#Process world
world.process(time_passed_seconds)
blank_surface = pygame.Surface(SCREEN_SIZE)
world.render(blank_surface) #The world class renders everything onto a blank surface
q_in.put((blank_surface, a))
screen.blit(q_out.get(), (0,0))
def DayNight():
while True:
blank_surface, a = q_in.get()
imgarray = surfarray.array3d(blank_surface) # Here is where the new numpy stuff starts (AKA Day/Night cycle)
src = N.array(imgarray)
dest = N.zeros(imgarray.shape)
dest[:] = 20, 30, 120
diff = (dest - src) * a
xfade = src + diff.astype(N.int)
surfarray.blit_array(blank_surface, xfade)
q_out.put(blank_surface)
q_in.task_done()
def main():
MainT = threading.Thread(target=run)
MainT.daemon = True
MainT.start()
DN = threading.Thread(target=DayNight)
DN.daemon = True
DN.start()
q_in.join()
q_out.join()
どなたか助けていただけると大変助かります。ありがとうございます。
ベストアンサー1
これはデーモンスレッドを使用する場合によくあることです。なぜ.daemon = True
スレッドを設定するのでしょうか? よく考えてみてください。デーモンスレッドには正当な用途もありますが、ほとんどプログラマーが混乱しているためにそうすることがよくあります。たとえば、「スレッドをきれいにシャットダウンする方法がわからないし、そうしないと終了時にプログラムがフリーズしてしまうので、わかっています。デーモン スレッドだとしましょう。そうすれば、インタープリターは終了時にそれらの終了を待たなくなります。問題は解決です。」
しかし、これは解決されず、通常は他の問題を引き起こすだけです。特に、デーモン スレッドは、インタープリタが終了時に自分自身を破壊している間も実行を続けます。モジュールが破壊され、stdin、stdout、stderr が破壊されるなど、さまざまな問題が発生します。デーモン スレッドがアクセスしようとするものが破壊されるため、さまざまな問題が発生する可能性があります。
あなたが見ている特定のメッセージは、あるスレッドで例外が発生したが、インタープリタの破壊が進みすぎてsys
モジュールに使用可能なものさえ残っていない場合に生成されます。スレッド実装は内部的に参照を保持しておりsys.stderr
、それをあなたに伝えることができます。何かその後 (具体的には、表示されている正確なメッセージ) が表示されますが、インタープリタの大部分が破壊されているため、何が問題だったのかについて他に何もわかりません。
したがって、代わりにスレッドをきれいにシャットダウンする方法を見つけてください(そして を削除してください.daemon = True
)。具体的な方法を提案できるほどあなたの問題については詳しくありませんが、何か思いつくでしょう ;-)
maxsize=0
ところで、コンストラクタの引数を削除することをお勧めしますQueue()
。デフォルトは「無制限」で、「誰もがそれを知っている」一方で、これmaxsize=0
も「無制限」を意味することを知っている人はほとんどいません。他のデータ型が「最大サイズは実際には 0 である」という意味になっているため、状況は悪化していますmaxsize=0
(その最良の例は ですcollections.deque
)。しかし、「引数がないということは無制限である」というのは、依然として普遍的に真実です。