referencing variable from function outside of the function - python

I am having trouble assigning a variable as global (i think this is my problem, at least).
Heres a representation of my code:
def get_alert():
global subject
# ...code ...
subject = # unread email's subject line
while True:
try:
get_alert()
except EOFError:
get_alert() # try again
else:
if subject == 'specific message here'
# ...code...
From what i've read assigning the variable as global at the top of the get_alert function should allow me to reference it in the while loop, however running the program it tells me, 'NameError: name 'subject' is not defined' for the subject in the while loop

You have to define subject before you use it, if you add
subject = None
at the beginning of your script, preferable after the imports, I think that will work.

Related

Trying to use a variable that is inside a function in another function

So I am trying to use a variable that is inside a function in another function.
One of them is the "message.py" file, that is in the folder "properties". The file looks like this:
def nachricht():
global msg
msg = input("Type: ")
return msg
The other file is the "badwords_check.py", that is in the folder "module". This file looks like this:
from properties.message import msg
from properties.badwords import BadWords
def badwords_check():
if any(word in msg for word in BadWords):
print("Dont use that word!")
else:
print("Message send!")
The problem now, is that I can't import "msg" from "message.py".
The error code looks like this:
from properties.message import msg
ImportError: cannot import name 'msg' from 'properties.message'
I had tried things like: Global, with/without function(without the function it works, but I need it with a function because some other code and files) and I tried return.
You need to declare the global variable outside the function at the top and then you can modify it inside your function using global msg.
msg= ''
def nachricht():
global msg
msg = input("Type: ")
return msg
To add on to Vaibhav's answer, the function nachricht() is never being called in badwords_check.py.
Hence, there is no input being taken and the variable msg also doesn't exist.
While declaring msg as a global variable, the function should also be called.
from properties.message import *
from properties.badwords import BadWords
#use nachricht()
#then use the below function
def badwords_check():
if any(word in msg for word in BadWords):
print("Dont use that word!")
else:
print("Message send!")
If nachricht() is not used, then msg will simply be a empty string.

NameError while calling a function (looking for a cleaner way to write the code)

I have a file which contains extracted data in the form of python variables.
I expect this data to always come in form of 2 variables(check, output_check).
The problem is that there are cases in which data is either incomplete(just the check variable) or data could not be extracted(meaning no variable at all).The contents of the file will always be different based on the data it extracted.
Here is an example of a file:
check_1 = "Warning, the check has failed"
output_check_1 = "Here is a more detailed result."
check_2 = "Warning, the check has failed"
#There is no output_check_2 variable
#There is no check_3 at all
Next up, a function will generate a report based on the data from the file:
def create_report(check, output_check):
if check.startswith("Warning"):
print(check)
if output_check:
print(output_check)
else:
print("Sorry, couldn't get a more detailed result")
else:
print("Check was successful.")
#Let's call the function
create_report(check_1, output_check_1) #Works
create_report(check_2, output_check_2) #-> NameError because in this case output_check_2 does not exist
create_report(check_3, output_check_3) #-> NameError because none of the arguments exist
As a fix, I came up with the following:
try:
create_report(check_2, output_check_2)
except NameError:
output_check_2 = ""
try:
create_report(check_2, output_check_2)
except NameError:
print("Error - data could not be extracted from the server!")
This way, if argument 2 (output_check_2) is missing I will just receive the result of the check without detailed data and if both arguments are missing(check_3, output_check_3) I am going to receive an error stating that the data could not be extracted at all.
The thing is that I find my "fix" rather barbaric and I am looking for a cleaner way in which to have the same result given that the function will be called many times during execution.
Edit: The variables come from an extraced_data.py file which I import at the start of the script. Unfortunately, I have no access to the script which generated the variables in the fist place thus encountering this issue.
Assuming there's no way to fix how the data is stored*, you could use getattr to deal with the missing data. I'm assuming that you're doing something like this to import:
from dataScript import *
Change that to this:
import dataScript
Then you can do:
check1 = getattr(dataScript, "check1", None) # Will default to None if it doesn't exist
if check1 is not None:
create_report(check_1, getattr(dataScript, "output_check1", None))
Or, if you're on Python 3.8+ and the check variable will never be an empty string:
if check1 := getattr(dataScript, "check1", None):
create_report(check_1, getattr(dataScript, "output_check1", None))
If you have an arbitrary number of these variables, you may need to use a loop. Something like:
for i in range(MAX_VARS):
n = i + 1
if check := getattr(dataScript, f"check{n}", None):
create_report(check_, getattr(dataScript, f"output_check{n}", None))
Where MAX_VARS is the highest variable that you're expecting.
* The input format here is really the issue though. Using a Python script as a database that only sometimes has the correct data seems like the real problem. My solution above is just a workaround.
You could also pass (*argv) instead of (check, output_check). This allows you to pass any number of arguments into your function.
def create_report(*argv):
if argv[0].startswith("Warning"): # argv[0] is your 'check' variable
print(argv[0])
if len(argv) > 1:
print(argv[1]) # argv[1] is your output_check variable
else:
print("No more info.")
else:
print("Check successful")
All you have to do is to change create_report function.
def create_report(check, output_check):
if not check:
print("Error - data could not be extracted from the server!")
return
if not output_check:
output_check = ""
if check.startswith("Warning"):
print(check)
if output_check:
print(output_check)
else:
print("Sorry, couldn't get a more detailed result")
else:
print("Check was successful.")
Now you can just call the function without try-except block.

Global variable not recognized in functions

I know that this question looks exactly like so many other on here, because I just read them all and they all say to do what I already tried, and it hasn't worked (or I'm missing a subtle difference with my situation). Here is my situation:
I am writing a scraper using Scrapy and Python 2.7.11, and my code looks like this (this is a copy and paste with irrelevant lines omitted, but I can re-add them upon request):
class LbcSubtopicSpider(scrapy.Spider):
...omitted...
rawTranscripts = []
rawTranslations = []
def parse(self, response):
#global rawTranscripts, rawTranslations
rawTitles = []
rawVideos = []
for sel in response.xpath('//ul[1]'): #only scrape the first list
...omitted...
index = 0
for sub in sel.xpath('li/ul/li/a'): #scrape the sublist items
index += 1
if index%2!=0: #odd numbered entries are the transcripts
transcriptLink = sub.xpath('#href').extract()
#url = response.urljoin(transcriptLink[0])
#yield scrapy.Request(url, callback=self.parse_transcript)
else: #even numbered entries are the translations
translationLink = sub.xpath('#href').extract()
url = response.urljoin(translationLink[0])
yield scrapy.Request(url, callback=self.parse_translation)
print rawTitles
print rawVideos
print rawTranslations
def parse_translation(self, response):
global rawTranslations
for sel in response.xpath('//p[not(#class)]'):
rawTranslation = sel.xpath('text()').extract()
rawTranslations.append(rawTranslation)
This will return an error any time either "print rawTranslations" or "rawTranslations.append(rawTranslation)" is called because the global "rawTranslations" is not defined.
As I said before, I have looked into this pretty extensively and pretty much everyone on the internet says to just add a "global (name)" line to the beginning of any function you'd use/modify it in (although I'm not assigning to it ever, so I shouldn't even need this). I get the same result whether or not my global lines are commented out. This behavior seems to defy everything I've read about how globals work in Python, so I suspect this might be a Scrapy quirk related to how parse functions are called through scrapy.Request(....).
Apologies for posting what appears to be the same question you've seen so much yet again, but it seems to be a bit twisted this time around and hopefully someone can get to the bottom of it. Thanks.
In your case the variable you want to access is not global, it is in the scope of the class.
global_var = "global"
class Example:
class_var = "class"
def __init__(self):
self.instance_var = "instance"
def check(self):
print(instance_var) # error
print(self.instance_var) # works
print(class_var) # error
print(self.class_var) # works, lookup goes "up" to the class
print(global_var) # works
print(self.global_var) # works not
You only need the global keyword if you want to write to a global variable. Hint: Don't do that because global variables that are written to bring nothing but pain and despair. Only use global variables as (config) constants.
global_var = "global"
class Example:
def ex1(self):
global_var = "local" # creates a new local variable named "global_var"
def ex2(self):
global global_var
global_var = "local" # changes the global variable
Example().ex1()
print(global_var) # will still be "global"
Example().ex2()
print(global_var) # willnow be "local"
if you want to use variable in class, you can use self.xxx
class A:
... var = []
... def test(self):
... self.var.append(10)
... print self.var

"SyntaxWarning: name 'our_mongo' is used prior to global declaration"

My code keeps giving me the above syntax warning. My code includes, but is not limited to:
class SocketHandler(WebSocketHandler):
def on_message(self, message):
ball = json.loads(message)
user = User(ball['identifier'])
if ball['command'] == 'search':
global our_mongo
search_results = our_mongo.find({'$text':{'$search':ball['search_term']}},{'score':{'$meta':"textScore"}})
self.write_message({
'command': 'search-results',
'results': list(search_results.sort([('score', {'$meta': 'textScore'})]).limit(10)),
})
elif ball['command'] == 'save-node': # hopefully this can handle both new nodes and changes to nodes
node_dict = ball['node_dict']
if 'importance' in node_dict.keys():
node_dict['importance'] = int(node_dict['importance'])
try:
node_obj = node.create_appropriate_node(node_dict)
print('node made. looks like: '+str(node_obj)+'. Now time to put it into the DB...')
global our_mongo
# take a look at the dependencies now
previous_dependency_ids = [node.reduce_string(dependency) for dependency in list(our_mongo.find({"_id": node_obj.id}))[0]["_dependencies"]] # if this works, try using set() instead of list and elimination the set()s below
print('prev deps are: '+str(previous_dependency_ids))
our_mongo.upsert({ "_id": node_obj.id }, node_obj.__dict__)
# take a look at the current dependencies
current_dependency_ids = [node.reduce_string(dependency) for dependency in list(our_mongo.find({"_id": node_obj.id}))[0]["_dependencies"]] # if this works, try using set() instead of list and elimination the set()s below
print('curr deps are: '+str(current_dependency_ids))
update_our_DAG()
# send an update of the graph to the user if there is a new dependency:
for new_dependency in set(current_dependency_ids) - set(previous_dependency_ids):
self.request_node(new_dependency, ball, user)
# OR IF THE SAVED NODE IS A BRAND NEW NODE, we have to include all the deps
except Exception as error:
# stuff didn't work, send error back to user
print('ERROR: '+str(error))
self.write_message({
'command': 'display-error',
'message': str(error),
})
def update_our_DAG():
# 1. grab nodes and edges from database
all_node_dicts = list(Mongo("math", "nodes").find())
# 2. create a networkx graph with the info...
global our_DAG
our_DAG = nx.DAG()
for node_dict in all_node_dicts:
node = create_appropriate_node(strip_underscores(node_dict))
our_DAG.add_n(node)
def make_app():
return Application(
[
url('/', RedirectHandler, {"url": "index.html"}, name="rooth"),
url('/websocket', SocketHandler),
url('/json', JSONHandler, name="jsonh"),
url(r'/index(?:\.html)?', IndexHandler, name="indexh"),
# captures anything at all, and serves it as a static file. simple!
url(r'/(.*)', StaticHandler, {"path": "../www/"}),
],
# settings:
debug=True,
)
def make_app_and_start_listening():
# enable_pretty_logging()
application = make_app()
# by listening on the http port (default for all browsers that i know of),
# user will not have to type "http://" or ":80" in the URL
application.listen(80)
# other stuff
IOLoop.current().start()
if __name__ == "__main__":
# 0. create a global mongo object for later use (for upserts in the future)
our_mongo = Mongo("math", "nodes")
# 1 and 2
update_our_DAG()
axioms = [our_DAG.n(node_id) for node_id in ['set', 'multiset', 'vertex']]
# 3. launch!
make_app_and_start_listening()
I've tried everything and it's still an issue. WHY is this a syntax error? What is the best way to fix this?
It is not a SyntaxError but a SyntaxWarning. Python warns that you're using our_mongo variable before a global our_mongo within the function.
Syntactically it does not actually matter on which line of the function the global statement is; but the idiomatic way would be to use global before the first access.
Another issue altogether is that you have multiple global our_mongo statements, where single would do, and also that you do not even need the global at all - it is only for the case when you want to assign a new value to the global variable; i.e.
def foo():
global bar # this line is required for the next line
# to change the global variable instead of
# the local variable
bar = 42
Thus, just remove all global statements altogether from your on_message, they're unnecessary.
The only reason a name is declared global in a function is so that it will be bound in global scope instead of local scope; when accessing a name the global scope is always searched regardless. Since your code never binds our_mongo within any function there is no reason to declare it global in the first place.

Having trouble with the self parameter

I am working on a small project and I am not sure if the error I am getting is due to the IDLE I am using or something I am doing wrong.
I am using OOP in python running on the Wing IDLE. I have the latest version of the python shell running on a Windows 8 PC.
In my program I have a method that takes user input and using that input it creates the parameters required to create a shelf.
'def subject_creator(self):
subject_name = input("Enter the subject name:")
subject_file = subject_name + "file"
name = subject_name
return subject_name, subject_file, name'
Ideally the program would then use the three returned statements namely subject_name, subject_file, and name in opening the new shelf.
'def __init__(self, subject_name, subject_file, name ):
subject_name = shelve.open ("subject_file", "c")
self.name = name
print("The", self.name ,"note has been created")'
while True:
print ("""
1.Create new note
2.Add new term
3.Look up term
4.Exit/Quit
""")
ans= input("What would you like to do?: ")
if ans=="1":
subject_creator()
note = Notebook(subject_name, subject_file, name)
subject_name.sync()
However when I run the program and in my main menu I select choice 1 which runs the code above, I receive and error that states.
<module>
builtins.TypeError: subject_creator() missing 1 required positional argument: 'self'
This is somewhat puzzling as I include the self parameter when I wrote the code for subject creator as shown above. Other than this I have no other errors.
Any feedback would be greatly appreciated.
You are confusing "function" and "method".
In Python, a method is a function defined inside a class scope, and it will receive the object as its implicit first argument:
class Example:
def try_me(self):
print "hello."
You would use it like this:
x = Example()
x.try_me()
and try_me() will receive x as its first (here, ignored) argument. This is useful so that the method can access the object instance's attributes etc.
Contrast this with a regular function, i.e. one defined outside of a class:
def try_me_too():
print "hello."
which is simply invoked like
try_me_too()
Tangentially, your example code does not pick up the values returned by your subject_creator function:
> if ans=="1":
> subject_creator()
> note = Notebook(subject_name, subject_file, name)
The scope where this happens doesn't have variables named subject_name etc. You need to create them somehow.
if ans=="1":
ick, bar, poo = subject_creator()
note = Notebook(ick, bar, poo)
(I chose nonsense variable names mainly to emphasize that these are different from the variables defined, and only available, inside subject_creator.)
Just to complete this, here is a demonstration of how self is useful.
class Otherexample:
def __init__(self, greeting):
self.greeting = greeting
def try_me_also(self):
print self.greeting
use like this:
y = Otherexample("hello.")
y.try_me_also()
Here, the greeting is a property of the object we created; the __init__ method receives it as its argument, and stores it as an attribute of the instance. The try_me_also method uses self to fetch this attribute, and print it.
This line causes your error
subject_creator()
You should change
def subject_creator(self):
subject_name = input("Enter the subject name:")
subject_file = subject_name + "file"
name = subject_name
return subject_name, subject_file, name
to
def subject_creator():
subject_name = raw_input("Enter the subject name:")
subject_file = subject_name + "file"
name = subject_name
return subject_name, subject_file, name
You don't need a parameter in your function if you won't use it.
Also,if you are using python 2.x, consider using raw_input() and not input(). For more info, please read differences between input() and raw_input().

Categories

Resources