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

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

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

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

受付中

【pyqt】thread処理が動作していない原因を教えてほしい

GuhChi
GuhChi

総合スコア0

Python

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

1回答

0評価

0クリップ

23閲覧

投稿2021/01/16 12:55

編集2022/01/12 10:55

前提・実現したいこと

実現したいこと
GUI操作でtwitterのいいね、リツイート、フォローを自動実行するアプリ作成

シングルスレッド処理だと自動実行中にGUIがフリーズしてしまい、
停止ボタンによる処理の終了
結果表示ができないため
自動実行部分をスレッドに渡してGUI操作ができるようにしたい

twitter操作にはtweepy
GUIはpyqt5
スレッド処理はQThread

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

自動実行部分をスレッド(QThread)に渡すと自動実行処理が実行されない

メインウィンドウpython↓

python

from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * import MainWindow import sys from twitter import twitterApp class MainWindow(QDialog,MainWindow.Ui_MainWindow): def __init__(self,parent=None): super(MainWindow,self).__init__(parent) self.setupUi(self) self.tw_app = twitterApp(self) self.executor = concurrent.futures.ThreadPoolExecutor(max_workers=3) self.setting = mngSetting() self.init_stylesheet = "background-color: rgb(167, 167, 167);" self.thread = QThread() self.act_list = [] def autorun(self): # 自動実行が開始されたら自動実行ボタンをクリックできないようにする self.changeBtnStatus(self.pushButton_2,self.pushButton) self.tw_app.moveToThread(self.thread) # スレッドからの紐づけ self.tw_app.sendFlag.connect(self.outAction) self.tw_app.sendMessage.connect(self.outLog) self.tw_app.sendCount.connect(self.setCount) self.thread.start() def outAction(self,rt,like,follow): if(rt): rt_act = 'RT' else: rt_act = '-' if(like): like_act = 'Like' else: like_act = '-' if(follow): follow_act = 'Follow' else: follow_act = '-' # action_listに今回作成したリストを追加していく tmp_list = [rt_act,like_act,follow_act,datetime.datetime.now()] self.act_list.append(tmp_list) # 行数を追加していく必要があるため # 行名は1から順に数字にしていく self.tableWidget.setRowCount(len(self.act_list)) tmpHeaders = list(range(1,len(self.act_list))) verHeaders = [str(n) for n in tmpHeaders] self.tableWidget.setVerticalHeaderLabels(verHeaders) for n in range(len(self.act_list)): for m in range(len(tmp_list)): item = QTableWidgetItem(str(self.act_list[n][m])) self.tableWidget.setItem(n, m, item) def outLog(self,message): log_message = '[' + str(datetime.datetime.now()) + '] ' + message self.listWidget.addItem(log_message) def setCount(self,like_count,rt_count,follow_count): self.label_14.setText(str(like_count)) self.label_17.setText(str(rt_count)) self.label_18.setText(str(follow_count)) if __name__ == "__main__": app = QApplication(sys.argv) form = MainWindow() form.show() app.exec_()

twitter機能実装pythonファイル↓

python

# twitterApp import tweepy from config import CONFIG from TwitterOauth import TwitterOauth from selenium import webdriver from selenium.webdriver.chrome.options import Options import time import oauth2 as oauth import json import datetime from PyQt5.QtWidgets import * from PyQt5.QtCore import * import schedule class twitterApp(QThread): # twitterAPIを使用する設定 # APPを起動した際に初期化 MAX_COUNT = 10 sendCount = pyqtSignal(int,int,int) sendFlag = pyqtSignal(bool,bool,bool) sendMessage = pyqtSignal(str) finished = pyqtSignal() def __init__(self,host_window): super(twitterApp,self).__init__() self.CONSUMER_KEY = CONFIG["API_KEY"] self.CONSUMER_SECRET = CONFIG["API_SECRET_KEY"] self.twitterOauth = TwitterOauth(self.CONSUMER_KEY,self.CONSUMER_SECRET) self.api ='' self.window = host_window self.follow_count = self.MAX_COUNT self.retweet_count = self.MAX_COUNT self.favorite_count = self.MAX_COUNT def run(self): """ QThreadのrunメソッドのオーバーライド """ self.autoWrapper(self.window.checkBox_4.isChecked(),self.window.lineEdit_4.text(),self.window.checkBox.isChecked(),self.window.checkBox_2.isChecked(),self.window.checkBox_3.isChecked(),self.window.spinBox.value()) #キーワード検索からtwitterの自動実行 def autoRunFromKeyWordSearch(self,word,favorite,retweet,follow,seconds): """twitterキーワード検索から操作実行 チェックをつけてある動作をキーワード検索に基づいて自動実行する Args: word: 検索キーワード favorite : いいねを実行するフラグ retweet: リツイートを実行するフラグ follow: フォローを実行するフラグ seconds: 実行間隔(s) """ self.sendMessage.emit('キーワード検索に対する自動実行を開始!') # self.outLog('キーワード検索に対する自動実行を開始!') search_results = self.api.search(q=word,count=self.MAX_COUNT) for result in search_results: tweet_id = result.id user_id = result.user._json['id'] if(favorite and self.favorite_count > 0): try: self.api.create_favorite(tweet_id) self.favorite_count -= 1 # self.window.label_14.setText(str(self.favorite_count)) if(self.favorite_count <= 0): break except Exception as e: favorite = False print(e) if(retweet and self.retweet_count > 0): try: self.api.retweet(tweet_id) self.retweet_count -= 1 # self.window.label_17.setText(str(self.retweet_count)) if(self.retweet_count <= 0): break except Exception as e: retweet = False print(e) if(follow and self.follow_count >= 0): try: self.api.create_friendship(user_id) # self.window.label_17.setText(str(self.retweet_count)) self.follow_count -= 1 if(self.follow_count <= 0): break except Exception as e: follow = False print(e) self.sendFlag.emit(retweet,favorite,follow) self.sendCount(self.favorite_count,self.retweet_count,self.follow_count) # self.outAction(retweet,favorite,follow) QThread.sleep(seconds) if(self.favorite_count <=0 and self.retweet_count <= 0): self.stop() self.sendMessage.emit('キーワード検索に対する自動実行を終了!') # self.outLog('キーワード検索に対する自動実行を終了!') self.window.changeBtnStatus(self.window.pushButton,self.window.pushButton_2) #タイムラインによるtwitterの自動実行 def autoRunAgainstTimeLine(self,favorite,retweet,seconds): """twitterタイムラインに対して操作実行 チェックをつけてある動作をタイムラインに基づいて自動実行する Args: favorite : いいねを実行するフラグ retweet: リツイートを実行するフラグ follow: フォローを実行するフラグ seconds: 実行間隔(s) """ self.sendMessage.emit('フォロワーに対する自動実行を開始!') # self.outLog('フォロワーに対する自動実行を開始!') # タイムラインのツイートを取得 tl = self.api.home_timeline(count=self.MAX_COUNT) for tweet in tl: tweet_id = tweet.id if(favorite and self.favorite_count >= 0): try: self.api.create_favorite(tweet_id) self.favorite_count -= 1 # self.window.label_14.setText(str(self.favorite_count)) except Exception as e: favorite = False print(e) if(retweet and self.retweet_count >= 0): try: self.api.retweet(tweet_id) self.retweet_count -= 1 # self.window.label_17.setText(str(self.retweet_count)) except Exception as e: retweet = False print(e) # self.outAction(retweet,favorite,False) self.sendFlag.emit(retweet,favorite,False) self.sendCount.emit(self.favorite_count,self.retweet_count,self.follow_count) QThread.sleep(seconds) if(self.favorite_count <=0 and self.retweet_count <= 0): self.stop() self.sendMessage.emit('フォロワーに対する自動実行を終了!') self.window.changeBtnStatus(self.window.pushButton,self.window.pushButton_2) def autoWrapper(self,is_tl,word,favorite,retweet,follow,seconds): """ @概要 自動実行する2つのメソッドのwrapper @param is_tl:タイムラインに対して自動実行するかのフラグ @param word:検索キーワード @param favorite:いいねフラグ @param retweet:リツイートフラグ @param follow:フォローフラグ @seconds: 実行間隔フラグ """ if(is_tl): self.autoRunAgainstTimeLine(favorite,retweets) if(word): self.autoRunFromKeyWordSearch(word,favorite,retweet,follow,seconds)

全ては書けなかったので追記します。
とりあえず、メインウィンドウ側のファイルを記載しました。

良い質問の評価を上げる

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

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

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

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

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

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

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

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

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

qnoir
qnoir

2021/01/16 13:55 編集

MainWindowクラスのautorun\(\)関数内で、threadがstartしたときの紐付けがなされていないのが原因かと思いますが、 signalとemitが書かれてあるであろう、twitterAppの内容が明らかにされていないので、はっきりしません。 twitter\.py(twitterAppクラスが書かれてあるファイル)のコードも全部提示していただけないでしょうか。 あと現状のコードだと、autorun\(\)関数(バックグラウンドでのtwitterのデータ取得処理?)自体は、MainWindow内部のどこからも呼び出されていないように見えますが、実際はMainWindowに何かボタンを実装して、そこをクリックしたら処理させるようなイメージなのでしょうか。
GuhChi
GuhChi

2021/01/16 15:23 編集

autorunをボタンと紐付けようとしています ''' import tweepy from config import CONFIG from TwitterOauth import TwitterOauth from selenium import webdriver from selenium\.webdriver\.chrome\.options import Options import time import oauth2 as oauth import json import datetime from PyQt5\.QtWidgets import \* from PyQt5\.QtCore import \* import schedule class twitterApp\(QThread\): # twitterAPIを使用する設定 # APPを起動した際に初期化 MAX_COUNT = 10 sendCount = pyqtSignal\(int,int,int\) sendFlag = pyqtSignal\(bool,bool,bool\) sendMessage = pyqtSignal\(str\) finished = pyqtSignal\(\) def __init__\(self,host_window\): super\(twitterApp,self\)\.__init__\(\) self\.CONSUMER_KEY = CONFIG\["API_KEY"\] self\.CONSUMER_SECRET = CONFIG\["API_SECRET_KEY"\] self\.twitterOauth = TwitterOauth\(self\.CONSUMER_KEY,self\.CONSUMER_SECRET\) self\.api ='' self\.window = host_window self\.follow_count = self\.MAX_COUNT self\.retweet_count = self\.MAX_COUNT self\.favorite_count = self\.MAX_COUNT def run\(self\): """ QThreadのrunメソッドのオーバーライド """ self\.autoWrapper\(self\.window\.checkBox_4\.isChecked\(\),self\.window\.lineEdit_4\.text\(\),self\.window\.checkBox\.isChecked\(\),self\.window\.checkBox_2\.isChecked\(\),self\.window\.checkBox_3\.isChecked\(\),self\.window\.spinBox\.value\(\)\) def login\(self,login_id,password\): """twitterにログイン twitterにログインするメソッド seleniumを利用してPINコードを取得→アクセストークンを取得する Args: login_id\(str\): twitterにログインするID @を付けること password : twitterにログインするPW Returns: user_name: twitterのユーザー名 friends_count: フォロー数 follower_count: フォロワー数 Raises: Examples: Note: PINコードが表示される時間によってエラーが発生する """ option = Options\(\) option\.add_argument\('--headless'\) # 認証ページのURLを取得する authenticate_url = self\.twitterOauth\.get_authenticate_url\(\) # driverを利用してログインする # driver = webdriver\.Chrome\(options=option\) driver = webdriver\.Chrome\(options=option\) driver\.get\(authenticate_url\) time\.sleep\(3\) # 画面に表示されたPINコードを取得する idForm = driver\.find_element_by_id\('username_or_email'\) idForm\.send_keys\(login_id\) passForm = driver\.find_element_by_id\('password'\) passForm\.send_keys\(password\) time\.sleep\(3\) loginButton = driver\.find_element_by_id\('allow'\) loginButton\.click\(\) pinCode = int\(driver\.find_element_by_tag_name\('code'\)\.text\) #PINコードを基にアクセストークンを取得する access_token_content = self\.twitterOauth\.get_access_token_content\(pinCode\) access_token = access_token_content\["oauth_token"\]\[0\] access_token_secret = access_token_content\["oauth_token_secret"\]\[0\] auth = tweepy\.OAuthHandler\(self\.CONSUMER_KEY,self\.CONSUMER_SECRET\) auth\.set_access_token\(access_token,access_token_secret\) driver\.close\(\) #tweepyのAPIを取得する self\.api = tweepy\.API\(auth\) # アカウント情報を取得する user_me = self\.api\.me\(\) return \[user_me\.name,user_me\.friends_count,user_me\.followers_count\] #キーワード検索からtwitterの自動実行 def autoRunFromKeyWordSearch\(self,word,favorite,retweet,follow,seconds\): """twitterキーワード検索から操作実行 チェックをつけてある動作をキーワード検索に基づいて自動実行する Args: word: 検索キーワード favorite : いいねを実行するフラグ retweet: リツイートを実行するフラグ follow: フォローを実行するフラグ seconds: 実行間隔\(s\) Returns: Raises: Examples: Note: """ self\.sendMessage\.emit\('キーワード検索に対する自動実行を開始!'\) # self\.outLog\('キーワード検索に対する自動実行を開始!'\) search_results = self\.api\.search\(q=word,count=self\.MAX_COUNT\) for result in search_results: tweet_id = result\.id user_id = result\.user\._json\['id'\] if\(favorite and self\.favorite_count > 0\): try: self\.api\.create_favorite\(tweet_id\) self\.favorite_count -= 1 if\(self\.favorite_count <= 0\): break except Exception as e: favorite = False print\(e\) if\(retweet and self\.retweet_count > 0\): try: self\.api\.retweet\(tweet_id\) self\.retweet_count -= 1 if\(self\.retweet_count <= 0\): break except Exception as e: retweet = False print\(e\) if\(follow and self\.follow_count >= 0\): try: self\.api\.create_friendship\(user_id\) self\.follow_count -= 1 if\(self\.follow_count <= 0\): break except Exception as e: follow = False print\(e\) self\.sendFlag\.emit\(retweet,favorite,follow\) self\.sendCount\(self\.favorite_count,self\.retweet_count,self\.follow_count\) QThread\.sleep\(seconds\) if\(self\.favorite_count <=0 and self\.retweet_count <= 0\): self\.stop\(\) self\.sendMessage\.emit\('キーワード検索に対する自動実行を終了!'\) self\.window\.changeBtnStatus\(self\.window\.pushButton,self\.window\.pushButton_2\) #タイムラインによるtwitterの自動実行 def autoRunAgainstTimeLine\(self,favorite,retweet,seconds\): """twitterタイムラインに対して操作実行 チェックをつけてある動作をタイムラインに基づいて自動実行する Args: favorite : いいねを実行するフラグ retweet: リツイートを実行するフラグ follow: フォローを実行するフラグ seconds: 実行間隔\(s\) """ self\.sendMessage\.emit\('フォロワーに対する自動実行を開始!'\) # タイムラインのツイートを取得 tl = self\.api\.home_timeline\(count=self\.MAX_COUNT\) for tweet in tl: tweet_id = tweet\.id if\(favorite and self\.favorite_count >= 0\): try: self\.api\.create_favorite\(tweet_id\) self\.favorite_count -= 1 except Exception as e: favorite = False print\(e\) if\(retweet and self\.retweet_count >= 0\): try: self\.api\.retweet\(tweet_id\) self\.retweet_count -= 1 except Exception as e: retweet = False print\(e\) self\.sendFlag\.emit\(retweet,favorite,False\) self\.sendCount\.emit\(self\.favorite_count,self\.retweet_count,self\.follow_count\) QThread\.sleep\(seconds\) if\(self\.favorite_count <=0 and self\.retweet_count <= 0\): self\.stop\(\) self\.sendMessage\.emit\('フォロワーに対する自動実行を終了!'\) self\.window\.changeBtnStatus\(self\.window\.pushButton,self\.window\.pushButton_2\) def autoWrapper\(self,is_tl,word,favorite,retweet,follow,seconds\): """ @概要 自動実行する2つのメソッドのwrapper @param is_tl:タイムラインに対して自動実行するかのフラグ @param word:検索キーワード @param favorite:いいねフラグ @param retweet:リツイートフラグ @param follow:フォローフラグ @seconds: 実行間隔フラグ """ if\(is_tl\): self\.autoRunAgainstTimeLine\(favorite,retweets\) if\(word\): self\.autoRunFromKeyWordSearch\(word,favorite,retweet,follow,seconds\) def calcAfterOneHour\(self\): """ @概要 関数を実行してから1時間後の時間を算出する """ dt_now = datetime\.datetime\.now\(\) dt_hour = dt_now \+ datetime\.timedelta\(minutes=1\) # スケジュールーラに登録する際に時間表記にする必要があるため dt_hour = dt_hour\.strftime\('%H:%M'\) return dt_hour def resetCount\(self\): """ @概要 回数を最大回数に戻す """ self\.follow_count = self\.MAX_COUNT self\.retweet_count = MAX_COUNT self\.favorite_count = self\.MAX_COUNT self\.window\.label_14\.setText\(str\(self\.favorite_count\)\) self\.window\.label_17\.setText\(str\(self\.retweet_count\)\) self\.window\.label_17\.setText\(str\(self\.retweet_count\)\) quit = True def stop\(self\): self\.window\.outLog\('指定回数を超えたため1時間後まで処理を停止します'\) schedule\.every\(\)\.day\.at\(self\.calcAfterOneHour\(\)\)\.do\(self\.resetCount\) while True: schedule\.run_pending\(\) if\(quit\): self\.outLog\('自動実行を再開できます'\) self\.window\.changeBtnStatus\(self\.window\.pushButton,self\.window\.pushButton_2\) break time\.sleep\(60\) ''' こちらがtwitter\.pyの全体になります。
qnoir
qnoir

2021/01/17 05:35

回答しました。なお、上のコメント欄にペーストしていただいているソース部分はインデントがないため考慮していません。

まだ回答がついていません

会員登録して回答してみよう

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

ただいまの回答率
87.20%

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

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

質問する

関連した質問

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

Python

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