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

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

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

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

Q&A

解決済

1回答

1218閲覧

pythonで、whileと乱数を組み合わせて、「一定の確率で関数を実行→また一定確率で実行」これを繰り返したい

退会済みユーザー

退会済みユーザー

総合スコア0

Python

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

1グッド

1クリップ

投稿2021/07/02 14:46

編集2021/07/03 09:57

前提・実現したいこと

タイトル通り、pythonで、whileと乱数を組み合わせて、一定の確率で関数を実行→また一定確率で実行→これを繰り返す、という感じにしたいです。ですが、下のwhile文が鬼門です。。
while文を無限ループさせて、関数bot_1を一定確率で実行するようにしたいですが、「syntax error」とpython本体から
エラーメッセージが来たり、起動しなかったりと、なかなか上手くいきません。(初心者なもので。。。)
※補足 開発にはatomエディタ,実行にはatom-runner を使用しています。

###該当するソースコード

python

1import tkinter 2import ctypes 3try: 4 ctypes.windll.shcore.SetProcessDpiAwareness(True) 5except: 6 pass 7 8###bot 9def bot_1(): 10 chat.insert(tkinter.END,"bot"+">>>test1"+"\n") 11def bot_2(): 12 chat.insert(tkinter.END,"bot"+">>>test2"+"\n") 13def bot_3(): 14 chat.insert(tkinter.END,"bot"+">>>test3"+"\n") 15def bot_4(): 16 chat.insert(tkinter.END,"bot"+">>>test4"+"\n") 17 18root = tkinter.Tk() 19root.title("test") 20root.geometry("450x800") 21root.resizable(width=0, height=0) 22 23chat = tkinter.Text() 24chat.place(x=40,y=0,width=369,height=500) 25 26import random 27##問題の部分。ここを無限ループさせ、関数bot_1を一定確率で実行するようにしたい 28while True: 29 r = random.randint(1,100) 30 if 2 == r: ##乱数と2が一致したら、関数bot_1を実行...したい 31 bot_1() 32root.mainloop()

何か、よい案はないでしょうか。。。。
そもそも、このコード自体が駄目なら、全く違う方法でも大丈夫です。
回答よろしくお願いします。

Nova124👍を押しています

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

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

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

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

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

BeatStar

2021/07/02 14:53

まず、プログラミングは『書いて終わり』ではないです。 デバッグやテストも含みます。 プロでもデバッグぐらいはします。 また、『エラーメッセージぐらいは読みましょう』。 エラーメッセージは怒声でも罵倒でも罵声でもハラスメントでもなく、 コンパイラやインタプリタ等からのメッセージです。 今の状態は『相手の話を聞かずに逆ギレしている人』です。 そんな人はコミュニケーションなんて取れないですよね。 まずはエラーメッセージを読み、デバッグぐらいはしましょう。
y_waiwai

2021/07/02 15:03

提示のコードではどういう動作になるんでしょうか。 また、それをどうしたいんでしょう
退会済みユーザー

退会済みユーザー

2021/07/03 05:49 編集

>>>y_waiwaiさん このコードは実行すると、guiが起動しません。 あとやりたいことですが、自分の言葉足らずで申しわけないのですが、 一定の確率で関数bot_1を実行→また一定確率で実行→これを繰り返す というのをやりたいです。 言葉足らずですみません。 >>>BeatStarさん 僕も何回もデバッグしてみて、それでもエラーメッセージ・起動しないといった現象が起きてしまい、僕の少ない知識では難しいかなと思い、質問させていただきました。 「投げられる」等の文章は、ただの一種の表現であり、「送られてくる」という意味で使わせていただきました。 誤解を生んだのなら申し訳ありません。よろしくお願いします。 ※通知で、「開発環境の情報w」となっていますが、正しくは「開発環境の情報を追加しました。」です 何回もすみません。(_ _)
BeatStar

2021/07/03 07:10

別に『できない』ことが悪いわけではありません。 プログラミングは奥が深いので、プロでもまだまだのようです。 私が問題視しているのは『質問方法を工夫していないこと』です。 ご自分の質問を『第三者的視点で』、 『フラットな状態で』読んでみてください。 『どのようなことを試したか』 『参考にしたサイト』等が はっきりとわかりますか? 回答者は質問者と同じ環境にある…わけではありません。 質問に『試したこと』等を書けば、 「この可能性はないなぁ…じゃあこの可能性は?」のように推測できます。 ですが『うまくいかない』とかみたいな質問だと回答者も完全に手探り状態でやるので双方にとって不毛です。 挙げ句の果てには『それ試したけどできねーから聞いてんだろが!』のような逆ギレする質問者が多いです。 (質問者さんはそういうタイプじゃないけど、マジで多いので) なので質問方法を工夫しましょう。
退会済みユーザー

退会済みユーザー

2021/07/03 09:41 編集

>>>BeatSterさん ご指摘の通り、読んでみたらわかり辛い文章になっていました。以後、もう少しわかりやすく書くように気をつけます。。有難うございました!
guest

回答1

0

ベストアンサー

問題点:
GUIプログラミング等では、ウィンドウを稼働させるためのイベントループを持つ為
通常のループ処理を同スレッドで行うことは出来ません。


簡易的な回避策: イベントループをループ内で明示的に呼び出す方法

python

1import random 2while True: 3 root.update() # GUI イベントを動かすために必要 4 5 r = random.randint(1,100) 6 if 2 == r: ##乱数と2が一致したら、関数bot_1を実行...したい 7 bot_1() 8 9# root.mainloop()

この場合は、mainloop() は使いません。
ループが重複する為、他の問題の原因になることがあります。

プログラムが複雑になり、root.update() が呼ばれないと、
ウィンドウが応答なしになってしまう点に注意。


おすすめの解決策: ジェネレーター&タイマーを使う方法

タイマーを使う方法が順当な解決策ですが、普通に書くと
コードはコールバック関数を呼び出す再帰的な記述になってしまいます。

while 文でコードを記述したい場合は、少し工夫が必要です。

マルチスレッドでも while 文でループを使った記述は出来ますが、
スレッドの場合はマルチスレッドでの同期・排他制御等の別の課題も出てくる為、

オススメは、ジェネレーターとして実装してタイマーで実行する方法です。

python

1 2def random_loop(): 3 import random 4 while True: 5 6 yield 0.01 # 10msのウェィト。ここは確率次第で、適切に設定する。 7 8 r = random.randint(1,100) 9 if 2 == r: ##乱数と2が一致したら、関数bot_1を実行...したい 10 bot_1() 11 12 13def gen_timer(gen): # ジェネレーターをタイマーで消化する関数 14 def _step(): 15 if n := next(gen, None): 16 root.after(int(n * 1000), _step) 17 _step() 18 19root.after_idle(gen_timer, random_loop()) # 開始 20 21root.mainloop()
  • ループ処理を関数にします。
  • ループ内で yield を使う。
  • ジェネレーターをタイマーで消化する仕組み(gen_timer)で呼び出す。

投稿2021/07/02 16:03

teamikl

総合スコア8760

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

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

退会済みユーザー

退会済みユーザー

2021/07/03 09:45

このコードを組み込んで実行してみたところ、無事できました!!本当に有り難うございました!!<(_ _)>ベストアンサーとさせていただきます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問