How to check if a function ran without generating any errors - python

I want to check to see if a message() function ran correctly and managed to send the message, the user could be out of reach for a certain time so I want to script to skip over his name it didn't manage to message him, and to mark the name of people it send a message to
I tried to set a bool value
That changes after the function runs but it doesn't seem to work, i'm using a modular to send the message I recive error on the modular not the script itself
user_was_messaged = False
def message_user()
user_was_messaged = True

If your user_was_messaged variable is global, then you need to use the global Python statement to change the value from within your function:
user_was_messaged = False
def message_user():
global user_was_messaged
user_was_messaged = True
However, using a global variable for this purpose would be highly discouraged. Instead, use the return value of the function:
def message_user():
# do things to try to send a message
if cannot send:
return False
# maybe do more things
return True
if message_user():
print("successful")
else:
print("failed")

As you have the variable user_was_messaged before the function, you must declare the variable as global in the function as in like:
user_was_messaged = False
def message_user()
global user_was_messaged
user_was_messaged = True

Related

How to access a variable outside of a class function if it wasn't passed to the function

I have been tasked to modify the behavior of a function in one of our Python classes.
Our function takes a few parameters, one being a debug flag. Currently the if the debug flag is not specified then we assume it to be False. What we need it to do is when debug is not specified, check the variable "debug" from the calling code and use that value, if it exists.
I would simply change the name of the debug parameter in the function declaration, except that we have a lot of legacy code that uses that flag.
This is in Jupyter Lab, if it makes any difference.
Sample code:
class MyClass:
#classmethod
def fn(self, debug=None):
if debug is None:
try:
debug = parent.debug
except Exception as e:
print(e)
debug = "BAD"
return debug
debug = True
x = myClass
print( x.fn() )
I would want the output to be "True" but it ends up being:
global name 'parent' is not defined
BAD
Is what I am trying to do possible? If so, how?
Use globals()['debug'] instead.
Or replace your fn() method to:
#classmethod
def fn(self, debug=None):
if debug is None:
debug = globals().get('debug', 'BAD')
return debug
You access variable parent which us not defined in your code.
Firstly, the MyClass in your code isn't inherited from any other class. Technically, the class doesn't have any parent(except the obj class by default), so it's impossible to access something that doesn't exist like 'parent.debug'. Secondly, as for your problem, I'm assuming that you want to access the debug variable that is initialized outside the class then you can easily do that by doing something like this:
global debug
class MyClass:
#classmethod
def fn(self, debug=None):
if debug is None:
try:
debug = debugOut
except Exception as e:
print(e)
debug = "BAD"
return debug
debugOut = True
x = MyClass()
print(x.fn())
The above code returns True

Use variables of imported files

So I have this file with the following code
async def check_server_restriction(ctx):
restriction = await get_restriction()
global check
if restriction[str(ctx.channel.id)]["Server"] == 1:
await ctx.send("This command is restricted. You can use it in the #bot-commands channel")
check = True
And I have another file that looks like this:
from channel_restrictions_functions import test_187, new_restriction, get_restriction, check_server_restriction, check
class whois(commands.Cog):
def __init__(self, client):
self.client = client
#commands.command()
async def whois(self, ctx, member:discord.Member = None):
await test_187()
await new_restriction(ctx)
await check_server_restriction(ctx)
#print(check)
if check == True:
print("Nicht perint")
return
So basically I import the function and try to import the variable too. The problem is now when the imported function gets activated and turns check (the variable) True (in theory) nothing happens. It should work like this when the thing is in the list it should send "This command is restricted" and set check true so that in my command the if statement works and it will return.
I dont get whats the mistake. I think it says check = False every time but it should be true
I hope you can understand my problem and you know how to fix it
thx for the help
Even global variables are not truly global, they are global only within the scope of their own module. There are ways to get around this restriction and share a variable between modules, if you absolutely have to, see e.g. here. It is recommended to put all global variables into a separate module and import from there, however, see the Python docs for more on this.
That said, why would you want to do this with a global variable? It's simpler and less error prone (in the sense that the restriction status would be shared between commands if global, which might lead to commands being falsely restricted) to just have check_server_restriction return True or False and then check the return value of the function something like this:
async def check_server_restriction(ctx):
restriction = await get_restriction()
if restriction[str(ctx.channel.id)]["Server"] == 1:
await ctx.send("This command is restricted. You can use it in the #bot-commands channel")
return True
return False
In your code, you'd then use this modified function like so:
if await check_server_restriction(ctx): # the == True can be omitted
print("Nicht perint")
return

Discord.Py Assigning values to variables

#commands.command()
async def reroll(self, ctx, channel: discord.TextChannel, id_ : int):
try:
new_gaw_msg = await ctx.channel.fetch_message(id_)
except:
await ctx.send("Failed to parse command. ID was incorrect.")
return
winners = int(winners.replace("W",""))
users_mention = []
for i in range(winners):
users = await new_gaw_msg.reactions[0].users().flatten()
users.pop(users.index(self.client.user))
winner = random.choice(users)
users_mention.append(winner.mention)
users.remove(winner)
displayed_winners = ",".join(users_mention)
await ctx.send(f"Congragulations {displayed_winners}! You have won the **{prize}**.\n{gaw_msg.jump_url}")
variable winners is referenced before assignment. I gave value to winners before using it so idk why it doesnt work. Any help is appreciated :D
You are trying to perform an operation on the winners variable before it was created.
There is a thing called name "namespace". Basically, variables created globally (without indent) and variables created locally (inside functions or loops) are different variables.
If you want to specifically use a global variable inside the function, you should first declare that the variable will be global by writing global variable_name inside the function. And only then you can perform operations with it.
There are some hidden dangers with the usage of global variables, so I suggest you read more about python namespaces and global keyword by yourself.

Access variable from Class in main

I'm trying to learn Python and I'm stuck with shared variables between classes.
I have a class that sets a variable like this:
class CheckStuff(threading.Thread):
def __init__(self, debug):
threading.Thread.__init__(self)
self.debug = debug
self.newGames = False
def get_new_games(self):
return self.newGames
def set_new_games(self, new_games):
self.newGames = new_games
def run(self):
# DO STUFF #
# ... #
self.set_new_games(True)
return
I would like to access new_games from my main, I tried like this:
if __name__ == "__main__":
debug = True
t1 = cs.CheckStuff(debug)
t1.start()
t1.join()
print(cs.CheckStuff(debug).get_new_games())
exit()
But this returns always False. Where am I wrong? Any hints appreciated
You're creating a new instance of CheckStuff, which hasn't done anything so its newGames attribute is False. The instance that did run is t1, you should use that:
print(t1.get_new_games())
(Note, there doesn't really seem to be a good reason to use threads here, but never mind.)
In the following line
print(cs.CheckStuff(debug).get_new_games())
you make a new instance of CheckStuff class, and in the constructor you set self.newGames = False. Then, by calling get_new_game() method you ask the object to return its newGame attribute, which is obviously False.

Why does globalising a boolean not work but globalising a dictionary does

This is just a question wondering why this doesn't work. I have figured out a better way, but I don't know why previously it wasn't working.
global mydict
mydict = {}
This seems to work fine, and has made the mydict dictionary global. I even print mydict and it works. However, doing this:
global bool
bool = False
Does not seem to work. If trying to print bool in my code, I get:
UnboundLocalError: local variable 'bool' referenced before assignment
So why does it work for the dictionary and not the boolean?
Oh, also, if anyone was wondering how I figured out a better way, I initialised a class and made bool global in the class by doing: self.bool = False which worked. I got it from this question: Making all variables global
EDIT: As requested, I'll post the necessary code:
import chatbot
global mydict
mydict = {}
global haveamessage
haveamessage = False
class MyBot(chatbot.ChatBot):
def __init__(self, username, password, site):
chatbot.ChatBot.__init__(self,username,password,site)
def on_message(self, c, e):
print mydict
print haveamessage
if __name__ == '__main__':
bot = MyBot("MyUsername", "MyPassword", "MySite")
bot.start()
I'll try explain this code. Pretty much the chatbot module is to allow users to create bots in wikis on Wikia, a company that allows wikis to be created which anyone can edit. On a wiki there is a chat extension where users can talk to. This script allows a bot to join the chat and do commands. on_message() goes off when someone posts something in the Chat.
So this prints:
{}
Traceback (most recent call last):
File "file.py", line 146, in <module>
bot.start()
File "/Library/Python/2.7/site-packages/chatbot.py", line 371, in start
self.on_message(self.c, e)
File "file.py", line 12, in on_message
print haveamessage
UnboundLocalError: local variable 'haveamessage' referenced before assignment
I'd like to clarify that the reason this isn't producing an error for all of you is because you are not in a Wikia chat. the function on_message() only runs when someone posts something in the Chat. For example, I may have:
def on_message(self, c, e):
if e.text == 'hello': # e.text is what a user posts in the chat. e = event
c.send('Hello!') # c.send simply sends back a message in the chat. c = connection
So when someone posts in chat hello, the Bot posts back Hello!
The code you've posted does not produce the error you claim it does. However using the global keyword outside of a function has no effect, so it's not surprising that it doesn't work like you expect.
I assume that in your real code, you're actually trying to assign to haveamessage inside on_message. If so, you need a global statement inside that method.
Basically the rule is: If you try to assign a global variable from within a function, you need to use the global keyword within that function. Otherwise you don't need the global keyword at all. Whether or not the variable is a boolean makes no difference.
I believe what you want to do is define the global variables, but then in your function reference them so you can use them locally:
import chatbot
mydict = {}
haveamessage = False
class MyBot(chatbot.ChatBot):
def __init__(self, username, password, site):
chatbot.ChatBot.__init__(self,username,password,site)
def on_message(self, c, e):
global mydict
global haveamessage
print mydict
print haveamessage

Categories