I have a module which has the following code
import DiscordoragiSearch
...
#Discord.client.event
async def on_message(message):
print('Message recieved')
#Is the message valid (i.e. it's not made by Discordoragi and I haven't seen it already). If no, try to add it to the "already seen pile" and skip to the next message. If yes, keep going.
if not (DiscordoragiSearch.isValidMessage(message)):
try:
if not (DatabaseHandler.messageExists(message.id)):
DatabaseHandler.addMessage(message.id, message.author.id, message.server.id, False)
except Exception:
traceback.print_exc()
pass
else:
await process_message(message)
Here is the relevant code from DiscordoragiSearch.py which is in the same directory as the other file.
#Checks if the message is valid (i.e. not already seen, not a post by Roboragi and the parent commenter isn't Roboragi)
def isValidMessage(message):
try:
if (DatabaseHandler.messageExists(message.id)):
return False
try:
if (message.author.name == USERNAME):
DatabaseHandler.addMessage(message.id, message.author.id, message.server.id, False)
return False
except:
pass
return True
except:
traceback.print_exc()
return False
This method is defined in the base of the module yet when I run the code I get the following error
File "/home/james/discordoragi/roboragi/AnimeBot.py", line 225, in on_message
if not (DiscordoragiSearch.isValidMessage(message)):
AttributeError: module 'DiscordoragiSearch' has no attribute 'isValidMessage'
Full code for both modules can be found here if you would like any more information I will try my best to provide it, this has been stumping me for over a month now so any help would be awesome, thanks!
Related
A more unusual question today, but maybe someone can help me.
I am working on a bot, which among other things has to do with music. The following problem:
If I change stuff in a cog and then reload it I always get an AttributeError: 'NoneType' object has no attribute 'XXXX' error for the particular command. Is there a way to fix/prevent this?
The error occurs when the bot is in a voice channel for example and then I reload the cog.
I query state for every command which has to do with music, is it maybe related to that?
state = self.get_state(ctx.guild)
Full function for get_state:
def get_state(self, guild):
"""Gets the state for `guild`, creating it if it does not exist."""
if guild.id in self.states:
return self.states[guild.id]
else:
self.states[guild.id] = GuildState()
return self.states[guild.id]
I tried to solve it with a try/except AttributeError, but of course that didn`t really work/the console still gave me the output.
Here is an example code:
#commands.command()
#commands.guild_only()
#commands.check(audio_playing)
#commands.check(in_voice_channel)
#commands.check(is_audio_requester)
async def loop(self, ctx):
"""Activates/Deactivates the loop for a song."""
state = self.get_state(ctx.guild)
status = state.now_playing.toggle_loop()
if status is None:
return await ctx.send(
embed=discord.Embed(title=":no_entry: Unable to toggle loop.", color=discord.Color.red()))
else:
return await ctx.send(embed=discord.Embed(
title=f":repeat: Loop: {'**Enabled**' if state.now_playing.loop else '**Disabled**'}.",
color=self.bot.get_embed_color(ctx.guild)))
And if I make changes in the cog, reload it and then try to run loop again I get the following error:
In loop:
File "C:\Users\Dominik\PycharmProjects\AlchiReWrite\venv\lib\site-packages\discord\ext\commands\core.py", line 85, in wrapped
ret = await coro(*args, **kwargs)
File "C:\Users\Dominik\PycharmProjects\AlchiReWrite\cogs\music.py", line 220, in loop
status = state.now_playing.toggle_loop()
AttributeError: 'NoneType' object has no attribute 'toggle_loop'
(Same error for all the other commands)
Requested, we have the GuildState class:
class GuildState:
"""Helper class managing per-guild state."""
def __init__(self):
self.volume = 1.0
self.playlist = []
self.message_queue = []
self.skip_votes = set()
self.now_playing = None
self.control_message = None
self.loop = False
self.skipped = False
def is_requester(self, user):
return self.now_playing.requested_by == user
How would I overcome this error?
The bot joins on the command play URL and then I built in the following:
if not state.now_playing:
self._play_song(client, state, video)
_play_song is mainly defined the following:
def _play_song(self, client, state, song):
state.now_playing = song
# Other things are not relevant
When you reload the cog, the states dictionary in your cog will be empty. With state = self.get_state(ctx.guild), a new GuildState object is created. From the __init__ function of the GuildState class, self.now_playing is set to None.
Because of this, status = state.now_playing.toggle_loop() will throw an AttributeError as None has no attributes (in this case, no toggle_loop attribute).
If you want to get rid of these errors, you will need to set self.now_playing correctly to something that does have the needed attributes.
If you want to keep the states dictionary as is, you can save it before reloading your cog and restore it. The below example assumes that the cog class is named TestCog.
#client.command()
async def reload(ctx):
temp = client.get_cog('TestCog').states
client.reload_extension('cog')
client.get_cog('TestCog').states = temp
Note that this may break your cog if you change how GuildState is created, as you are restoring the previous version of states.
I have a password recognition code that goes like this:
from wit import Wit
import pyttsx3, time
def speak(string):
engine = pyttsx3.init()
engine.setProperty('rate', 220)
engine.say(string)
engine.runAndWait()
def Hear():
recog = sr.Recognizer()
with sr.Microphone() as source:
audio= recog.listen(source)
print (audio)
return
wit_key = 'FO7EYTKK6OHRSZ3A5UFPMZOC7VIXCVSY'
try:
print('VEXD THINKS YOU SAID '+ recog.recognize_wit(audio, key=wit_key))
heard = recog.recognize_wit(audio, key=wit_key)
except sr.UnknownValueError:
print("I DIDN't get that")
except sr.RequestError as e:
print("SERVER DISCONECTED")
speak("CHECKING IDENTITY" )
sound = Hear()
time.sleep(1)
if "master"in sound:
speak("Yes My Lord")
It is supposed to say YEs my lord when I say master
but when I say master , it returns this error
File "c:/Users/tdmfa/OneDrive/Desktop/VEXD app/VEXD AI/AI_START.py", line 33, in <module>
if "master"in sound:
TypeError: argument of type 'NoneType' is not iterable
sound= Hear()
This line of code, doesn't receive any output from the Hear() function. Your Hear() function doesn't return any value, it simply exits the function and returns None. That is why it says
'NoneType' is not iterable, because you are trying to iterate over sound.
This should work:
from wit import Wit
import pyttsx3, time
import speech_recognition as sr
def speak(string):
engine = pyttsx3.init()
engine.setProperty('rate', 220)
engine.say(string)
engine.runAndWait()
def Hear():
recog= sr.Recognizer()
with sr.Microphone() as source:
audio= recog.listen(source)
wit_key = 'FO7EYTKK6OHRSZ3A5UFPMZOC7VIXCVSY'
try:
audio_str = recog.recognize_wit(audio, key=wit_key)
print('VEXD THINKS YOU SAID '+ audio_str)
return audio_str
except sr.UnknownValueError:
error1 = "I DIDN't get that"
print(error1)
return error1
except sr.RequestError as e:
error2 = "SERVER DISCONNECTED"
print(error2)
return error2
speak("CHECKING IDENTITY")
sound= Hear()
time.sleep(1)
if "master" in sound:
speak("Yes My Lord")
It looks like you should be returning heard from your Hear() function, instead of None as it currently does. There are two exit points in that function, both return None:
the call to return right after audio is obtained by the recogniser
implicitly when the function ends without calling return to return a specific value.
To fix, remove the return call just after the recogniser gets the audio, and then add return heard after heard = recog.recognize_wit(audio, key=wit_key). The function can still return None if one of the expected exceptions is raised, so you will want to probably want to return an empty list, or retry as appropriate.
I am not familiar with the libraries that you are using, so I am assuming that heard will be some kind of iterable (list, tuple, string, etc.) that makes sense to the rest of your code.
I think this should be a bit tricky but somehow feasible, but I need help.
I'd like to execute two functions from within my main() func.
I'd like to be able to catch exceptions from the two separately, but still being able to execute both and get the result of at least one of them if the other raises an exception.
Let's say I have:
def foo():
raise TypeError
def bar():
return 'bar'
If I do (adapted from here):
def multiple_exceptions(flist):
for f in flist:
try:
return f()
except:
continue
def main():
multiple_exceptions([foo, bar])
main()
main() would return 'bar', but I'd like to be able to still throw the exception from foo() after all. This way, I would still have the result of one of my functions and the information on the error occurred in the other.
You can capture and store the exceptions using 'as', e.g.:
try:
raise Exception('I am an error!')
print('The poster messed up error-handling code here.') #should not be displayed
except Exception as Somename:
print(Somename.message)
# you'll see the error message displayed as a normal print result;
# you could do print(stuff, file=sys.stderr) to print it like an error without aborting
print('Code here still works, the function did not abort despite the error above')
...or you can do:
except Exception as Somename:
do_stuff()
raise Somename
Thanks for the comments.
I solved by doing this:
def multiple_exceptions(flist):
exceptions = []
for f in flist:
try:
f()
except Exception as e:
exceptions.append(e.message)
continue
return exceptions
def main():
multiple_exceptions([foo, bar])
error_messages = main() # list of e.messages occurred (to be raised whenever I want)
Then I can raise my exception like e.g. raise Exception(error_messages[0]) (I only care about the first in this case let's say).
I'm running a PyQt5 UI that adds IP addresses through REST APIs. When sending operations to my worker Thread (runs a few for loops, and runs a few functions within those loops), whenever I get an exception thrown within the code...it will not print the exact error from json.loads.
My main goal is to get the exact err.read() of the the 4xx or 5xx error I receive, so to tell the user what exactly happened (the 4xx and 5xx errors will output, just not the json.loads(err.read()).)
def patch_object_group (f):
self.api_path = "/api/objects/networkobjectgroups/EXT-SFTPALLOWED/"
self.req = urllib.request.Request(str(server) + self.api_path, json.dumps(self.patch_data_group).encode('utf-8'), headers, method="PATCH") #Default Method is Post
self.base64string = base64.encodestring(('%s:%s' % (username,password)).encode()).decode().replace('\n', '')
self.req.add_header("Authorization", "Basic %s" % self.base64string)
try:
f = urllib.request.urlopen(self.req)#Had to add .request between the url for python 3.
self.status_code = f.getcode()
# print("Status code is {}.".format(self.status_code))
if self.status_code == 204:
print ("The following object was added to the group successfully: {}".format(self.patch_data_group["members.add"][0]["value"]))
jsonoutputlist.append(self.patch_data_group)
except urllib.error.HTTPError as err: #Python3 requires urllib.error.HTTPError to work.
print ("Error received from server: {}. HTTP Status code: {}".format(err.reason, err.code))
In this try statement, with logging and Printouts the code never makes it into the "if" statement...and it appears json.loads(err.read) doesn't actually read the error.
try:
json_error = json.loads(err.read)
if json_error: #Doesn't make it into the if statement when error is received.
print (json.dumps(json_error,sort_keys=True,indent=4, separators=(',', ': ')))
except ValueError:
pass
finally:
if f: f.close()
return (f)
I'm using the following in my main UI (not worker thread) to Emit all stdout's to the UI textbox.
class EmittingStream(QtCore.QObject):
textWritten = QtCore.pyqtSignal(str)
def write(self, text):
self.textWritten.emit(str(text))
def flush(self):
pass
Any assistance would be greatly appreciated.
Thanks,
Found the answer after further testing! json_error was receiving the error as bytes and not a str. I found that in my code I was just passing the ValueError...not error handling appropriately.
except ValueError:
pass
I added in the following:
except (TypeError, ValueError) as e:
print("Error: {}".format(e))
pass
This allowed me to see the exact error was a TypeError.
Found my json_error was actually passing as a byte and not a string. Added .decode() to my code and now it outputs the exact error.
json_error = json.loads(err.read().decode())
Trying to get the try/except statement working but having problems. This code will take a txt file and copy the file that is in location row 0 to location of row 1. It works however if i change one of the paths to invalid one it generates an error ftplib.error_perm however the except command is not picking up and everything stops. What am i doing wrong? Python 2.4
import csv
import operator
import sys
import os
import shutil
import logging
import ftplib
import tldftp
def docopy(filename):
ftp = tldftp.dev()
inf = csv.reader(open(filename,'r'))
sortedlist = sorted(inf, key=operator.itemgetter(2), reverse=True)
for row in sortedlist:
src = row[0]
dst = row[1]
tldftp.textXfer(ftp, "RETR " + src, dst)
def hmm(haha):
result = docopy(haha);
try:
it = iter(result)
except ftplib.error_perm:
print "Error Getting File"
if __name__ == "__main__":
c = sys.argv[1]
if (c == ''):
raise Exception, "missing first parameter - row"
hmm(c)
The except clause will only catch exceptions that are raised inside of their corresponding try block. Try putting the docopy function call inside of the try block as well:
def hmm(haha):
try:
result = docopy(haha)
it = iter(result)
except ftplib.error_perm:
print "Error Getting File"
The point in the code which raises the error must be inside the try block. In this case, it's likely that the error is raised inside the docopy function, but that isn't enclosed in a try block.
Note that docopy returns None. As such, you will raise an exception when you try to make an iter out of None -- but it won't be a ftplib.error_perm exception, it'll be a TypeError
If you are not sure of what exception will occur, the use the code below, because if especifies for example: except StandardError: and is not that error the exception will not be process.
try:
# some code
except Exception: # Or only except:
print "Error" # Python 3: print("Error")
I know the OP is ancient, but for folks desperate for answers on this question. I had a similar issue, depending on your IDE, if you have a breakpoint on any of the lines with specific exceptions etc, this can conflict and stop try/except executing.
I noticed global exception may not works, e.g. , Ctrl+C when epub.py module perform urllib3 connection trigger KeyboardInterrupt but not able to catch in main thread, the workaround is put my clean up code inside finally, e.g.:
try:
main()
except Exception as e:
clean_up_stuff() #this one never called if keyboard interrupt in module urllib3 thread
finally: #but this work
clean_up_stuff()
This example is generic for Python3.3+, when decorating a generator function, a decorated generator returns successfully, thus not entering the decorators except, the magic happens with yield from f thus wrapping the yieldable within the decorator:
from types import GeneratorType
def generic_exception_catcher(some_kwarg: int = 3):
def catch_errors(func):
def func_wrapper(*args, **kwargs):
try:
f = func(*args, **kwargs)
if type(f) == GeneratorType:
yield from f
else:
return f
except Exception as e:
raise e
return func_wrapper
return catch_errors
Usage:
#generic_exception_catcher(some_kwarg=4)
def test_gen():
for x in range(0, 10):
raise Exception('uhoh')
yield x
for y in test_gen():
print('should catch in the decorator')