我使用Python,Pysimplegui和Praw创建一个Reddit机器人。它在我的空闲中运行,但在转换为可执行文件后因螺纹错误而失败
我正在研究一个机器人,该机器人使用Praw在用户定义的子reddit中扫描所有新评论,并搜索要回复的特定短语。我已经在这里看到了pysimplegui作为用户界面,您可以在此处看到:
gui的图像,带有reddit的文本输入的GUI图像API授权
由于在长时间操作中冻结的问题,我必须实现线程。我的代码只要我在闲置(pycharm)中运行它就可以运行良好:
ERROR Unable to complete operation on element with key 0
File "PySimpleGUI\PySimpleGUI.py"
line 20892
in_error_popup_with_traceback
You cannot perform operations (such as calling update) on an Element until:
window.read() is called or finalize=True when Window created.
Adding a "finalize=True" parameter to your Window creation will likely fix this.
The PySimpleGUI internal reporting function is _widget_was_created
The error originated from:
File "threading.py"
line 1319
in invoke_excepthook
我已经在此工作了两天,没有进一步的进步,尽管我对Python来说是全新的,所以我敢肯定我缺少一些东西。这是我的完整代码:
#importing the necessary libraries
from threading import Thread
import praw
import subprocess
import sys
import time
from datetime import datetime
import PySimpleGUI as psg
#worker function
def bot(id, secret, key, agent, user, sub, keywords, body):
#initializes PRAW with user's credentials
reddit = praw.Reddit(
client_id=id,
client_secret=secret,
password=key,
user_agent=agent,
username=user)
#specifies which subreddit to perform the operation on
subreddit = reddit.subreddit(sub)
#initiates a live feed of new comments and checks for the user defined search term using for loops
for comment in subreddit.stream.comments():
if comment:
normalized_comment = comment.body.lower()
for phrase in keywords:
if phrase in normalized_comment:
#if the phrase is found, prints a timestamp and the comment to the console
current_time = datetime.now()
print(str(current_time) + " - Replying to: " + '"' + comment.body + '"')
#tries to reply to the comment found
try:
comment.reply(body=body)
# A reply has been made so do not attempt to match other phrases.
break
#if the bot is flagged for a cooldown, sleep for two minutes
except:
current_time = datetime.now()
print(str(current_time) + " - Rate limited, retrying in two minutes.")
time.sleep(120)
#this function creates the GUI
def gui():
psg.theme("Dark")
#layout for input window
layout = [[psg.Text("Personal Use Script", size=(15, 1), font='Lucida', justification='right'), psg.Input()],
[psg.Text("Secret", size=(15, 1), font='Lucida', justification='right'), psg.Input()],
[psg.Text("Bot Password", size=(15, 1), font='Lucida', justification='right'), psg.Input()],
[psg.Text("Bot Call Sign", size=(15, 1), font='Lucida', justification='right'), psg.Input()],
[psg.Text("Bot Username", size=(15, 1), font='Lucida', justification='right'), psg.Input()],
[psg.Text("Subreddit to Search", size=(15, 1), font='Lucida', justification='right'), psg.Input()],
[psg.Text("Trigger Phrase", size=(15, 1), font='Lucida', justification='right'), psg.Input()],
[psg.Text("Comment to Send", size=(15, 1), font='Lucida', justification='right'), psg.Input()],
[psg.Button("RUN", font=("Times New Roman", 12))]]
#this line initiates the GUI window
win = psg.Window("Find & Reply v 0.1", layout, finalize=True, element_justification='c')
#this line listens for any interactions with the elements on the window
e, v = win.read()
while True:
#closes the program if the window is closed
if e in (psg.WIN_CLOSED, 'Exit'):
break
#listens for the "RUN" button to be clicked and executes the bot function thread
if e == 'RUN':
#this line closes the initial input window
win.close()
bot_thread = Thread(target=bot, args=(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]))
bot_thread.start()
# layout for a secondary output window so the user can read the console
layout1 = [[psg.Output(size=(60, 15))]]
#initiates the secondary window
win1 = psg.Window("Scanning all new comments...", layout1, finalize=True, element_justification='c')
#listens for any interactions with the elements on the window
event, values = win1.Read()
#closes the program in the event the window is close (doesn't work)
if event in (psg.WIN_CLOSED, 'Exit'):
break
if event == 'Run': # the two lines of code needed to get button and run command
runCommand(cmd=values['_IN_'], window=win1)
win1.close()
#this function sends the console text to the secondary output window for the user to read
def runCommand(cmd, timeout=None, window=None):
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output = ''
for line in p.stdout:
line = line.decode(errors='replace' if (sys.version_info) < (3, 5) else 'backslashreplace').rstrip()
output += line
print(line)
window.Refresh() if window else None # yes, a 1-line if, so shoot me
retval = p.wait(timeout)
return (retval, output) # also return the output just for fun
if __name__ == '__main__':
#this is where I initiate the GUI thread
gui_thread = Thread(target=gui)
gui_thread.start()
I'm working on a bot that uses PRAW to scan all new comments in a user defined subreddit and searches for specific phrases to reply to. I've used PySimpleGUI for the user interface, as you can see here:
Image of GUI with text inputs for Reddit API authorization
Because of an issue where it freezes during long operations, I've had to implement threading. My code runs well as long as I'm running it in my IDLE (PyCharm), but after converting it to an executable, running it, entering my credentials along with the relevant terms, and clicking "RUN", I get a threading error:
ERROR Unable to complete operation on element with key 0
File "PySimpleGUI\PySimpleGUI.py"
line 20892
in_error_popup_with_traceback
You cannot perform operations (such as calling update) on an Element until:
window.read() is called or finalize=True when Window created.
Adding a "finalize=True" parameter to your Window creation will likely fix this.
The PySimpleGUI internal reporting function is _widget_was_created
The error originated from:
File "threading.py"
line 1319
in invoke_excepthook
Screenshot of this error message.
I've been working on this for two days now with no further progress, although I am brand new to python so I'm sure I'm missing something. Here is my full code:
#importing the necessary libraries
from threading import Thread
import praw
import subprocess
import sys
import time
from datetime import datetime
import PySimpleGUI as psg
#worker function
def bot(id, secret, key, agent, user, sub, keywords, body):
#initializes PRAW with user's credentials
reddit = praw.Reddit(
client_id=id,
client_secret=secret,
password=key,
user_agent=agent,
username=user)
#specifies which subreddit to perform the operation on
subreddit = reddit.subreddit(sub)
#initiates a live feed of new comments and checks for the user defined search term using for loops
for comment in subreddit.stream.comments():
if comment:
normalized_comment = comment.body.lower()
for phrase in keywords:
if phrase in normalized_comment:
#if the phrase is found, prints a timestamp and the comment to the console
current_time = datetime.now()
print(str(current_time) + " - Replying to: " + '"' + comment.body + '"')
#tries to reply to the comment found
try:
comment.reply(body=body)
# A reply has been made so do not attempt to match other phrases.
break
#if the bot is flagged for a cooldown, sleep for two minutes
except:
current_time = datetime.now()
print(str(current_time) + " - Rate limited, retrying in two minutes.")
time.sleep(120)
#this function creates the GUI
def gui():
psg.theme("Dark")
#layout for input window
layout = [[psg.Text("Personal Use Script", size=(15, 1), font='Lucida', justification='right'), psg.Input()],
[psg.Text("Secret", size=(15, 1), font='Lucida', justification='right'), psg.Input()],
[psg.Text("Bot Password", size=(15, 1), font='Lucida', justification='right'), psg.Input()],
[psg.Text("Bot Call Sign", size=(15, 1), font='Lucida', justification='right'), psg.Input()],
[psg.Text("Bot Username", size=(15, 1), font='Lucida', justification='right'), psg.Input()],
[psg.Text("Subreddit to Search", size=(15, 1), font='Lucida', justification='right'), psg.Input()],
[psg.Text("Trigger Phrase", size=(15, 1), font='Lucida', justification='right'), psg.Input()],
[psg.Text("Comment to Send", size=(15, 1), font='Lucida', justification='right'), psg.Input()],
[psg.Button("RUN", font=("Times New Roman", 12))]]
#this line initiates the GUI window
win = psg.Window("Find & Reply v 0.1", layout, finalize=True, element_justification='c')
#this line listens for any interactions with the elements on the window
e, v = win.read()
while True:
#closes the program if the window is closed
if e in (psg.WIN_CLOSED, 'Exit'):
break
#listens for the "RUN" button to be clicked and executes the bot function thread
if e == 'RUN':
#this line closes the initial input window
win.close()
bot_thread = Thread(target=bot, args=(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]))
bot_thread.start()
# layout for a secondary output window so the user can read the console
layout1 = [[psg.Output(size=(60, 15))]]
#initiates the secondary window
win1 = psg.Window("Scanning all new comments...", layout1, finalize=True, element_justification='c')
#listens for any interactions with the elements on the window
event, values = win1.Read()
#closes the program in the event the window is close (doesn't work)
if event in (psg.WIN_CLOSED, 'Exit'):
break
if event == 'Run': # the two lines of code needed to get button and run command
runCommand(cmd=values['_IN_'], window=win1)
win1.close()
#this function sends the console text to the secondary output window for the user to read
def runCommand(cmd, timeout=None, window=None):
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output = ''
for line in p.stdout:
line = line.decode(errors='replace' if (sys.version_info) < (3, 5) else 'backslashreplace').rstrip()
output += line
print(line)
window.Refresh() if window else None # yes, a 1-line if, so shoot me
retval = p.wait(timeout)
return (retval, output) # also return the output just for fun
if __name__ == '__main__':
#this is where I initiate the GUI thread
gui_thread = Thread(target=gui)
gui_thread.start()
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论