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

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

ただいまの
回答率

90.84%

  • Python

    5941questions

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

  • Python 3.x

    4471questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • Tkinter

    100questions

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

tkinterでRunTimeErrorを出ないようにしたい

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 66

ryota_adr

score 9

 前提・実現したいこと

tkinterでツイッターのクライアントを作っています。

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

×ボタンでプログラムを閉じると下記のエラーが出ます。
出ないようにするにはどうすればいいでしょうか?

  File "C:\Users\user\Anaconda3\envs\py36\lib\tkinter\__init__.py", line 2293, in __init__
    (widgetName, self._w) + extra + self._options(cnf))
RuntimeError: main thread is not in main loop

 該当のソースコード

import tweepy
from tkinter import *
from collections import deque

class TimeLine(Frame, tweepy.StreamListener):
    def __init__(self, master=None):
        #donsumer keyなど
        CK = "xxxxxxxx"
        CS = "xxxxxxxx"
        AT = "xxxxxxxx"
        ATS = "xxxxxxxx"

        Frame.__init__(self, master)
        self.master.title('Time Line')
        self.master.geometry("500x500")

        self.auth = tweepy.OAuthHandler(CK, CS)
        self.auth.set_access_token(AT, ATS)
        self.mylistener = MyListener()
        self.stream = tweepy.Stream(self.auth, self.mylistener)

        self.label_d = deque()
        self.stream.userstream(async=True)


    #新しいツイートを上に表示
    def make_tweet(self):
        for n in range(len(self.label_d)):
            self.label_d[n].grid(row=n, column=0)

class MyListener(tweepy.StreamListener):
    def on_status(self, status):
        self.new_msg = status._json
        self.tweet = '@' + self.new_msg['user']['screen_name'] + ' : ' +\
            self.new_msg['user']['name'] + '\n' + self.new_msg['text']
        #tkinterで表示できない文字を消す
        self.chr_list =  [self.tweet[j] for j in range(len(self.tweet)) \
            if ord(self.tweet[j]) in range(65536)]
        self.tweet = ''
        for i,j in enumerate(self.chr_list):
            self.tweet = self.tweet + j 
        t.label_d.appendleft(Label(t, text=self.tweet, width=50))
        t.make_tweet()

    def on_error(self, status_code):
        print('Error occured: ' + str(status_code))

if __name__ == '__main__':
    t = TimeLine()
    t.pack()
    t.mainloop()

 試したこと

ここに問題に対して試したことを記載してください。

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

ここにより詳細な情報を記載してください。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+2

推測です。

標準のPythonはリファレンスカウンター方式のガベージコレクションを採用してます。この方式においては、任意のPythonインスタンスはどの変数からも指されなくなった時点で即座に削除されます。I/O関連の機能を持つインスタンス(tweepy.Streamなど)はおそらくインスタンスが削除されるときに自動的に「OSに対する資源解放=クローズ」をするようになっていると思いますが、クローズされるまではずっと活動し続けています。

ウィンドウを閉じた時点で(どこでもクローズしてないので)tweepy.Streamは活動状態ですよね?つまりリスナーも起動される可能性があると思います。しかしウィンドウを閉じてmainloop関数の実行が終わってしまった後にリスナーが動いてしまうと(リスナーの中でtkinterのウィジェットにアクセスしているため)ご質問のような例外が発生するのではないでしょうか?

https://stackoverflow.com/questions/111155/how-do-i-handle-the-window-close-event-in-tkinter
この質問でウィンドウが閉じられたときに行うべき処理を登録できると書いてありますが、こうしたものを使って「mainloopが終了する前にすべき後始末※をしてみてはいかがでしょう?

※:例えばtweepy.Streamをしかるべき手順で「クローズ」したり、self.stream=Noneとすると改善するような気がします。(推測です)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/06 16:00 編集

    TimeLine()に

    def quit_GUI(self):
    self.stream.disconnect()
    self.master.destroy()

    を追加して

    if __name__ == '__main__':

    以下を

    root = Tk()
    t = TimeLine(root)
    t.pack()
    root.protocol("WM_DELETE_WINDOW", t.quit_GUI)
    root.mainloop()

    にしたらできました。
    ありがとうございます。

    キャンセル

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

  • ただいまの回答率 90.84%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Python

    5941questions

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

  • Python 3.x

    4471questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • Tkinter

    100questions

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