I am new to python and am trying to define a function and then use it in Google App Engine - but I keep getting the error "Error: global name 'cache_email_received_list' is not defined" when I try to execute the function. Any help would be greatly appreciated, thanks.
Here is my function:
class EmailMessageHandler(BaseHandler2):
def cache_email_sent_list(): #set email_sent_list to memcache
email_sent_list = db.GqlQuery("SELECT * FROM EmailMessage WHERE sender =:1 ORDER BY created DESC", user_info.username)
if email_sent_list:
string1 = "email_sent_list"
email_sent_list_cache_id = "_".join((user_info.username, string1))
memcache.set('%s' % email_sent_list_cache_id, email_sent_list, time=2000000)
logging.info('**************email_sent_list added to memcache*********')
Here is where I am trying to call it:
if email_received_list is None and email_sent_list is not None:
params = {
'email_sent_list': email_sent_list,
}
cache_email_sent_list()
cache_email_sent_list() is a method of the class EmailMessageHandler therfore the method needs to pass in self a a parameter it will therefore look like this:
class EmailMessageHandler(BaseHandler2):
def cache_email_sent_list(self): #set email_sent_list to memcache
email_sent_list = db.GqlQuery("SELECT * FROM EmailMessage WHERE sender =:1 ORDER BY created DESC", user_info.username)
if email_sent_list:
string1 = "email_sent_list"
email_sent_list_cache_id = "_".join((user_info.username, string1))
memcache.set('%s' % email_sent_list_cache_id, email_sent_list, time=2000000)
logging.info('**************email_sent_list added to memcache*********')
Then when you call it from within the class EmailMessageHandler you have to do it like this:
self.cache_email_sent_list()
If however you are calling it from outside the class EmailMessageHandler you need to first create an instance and then call it using:
instanceName.cache_email_sent_list()
Just as an addition to the previous answers: In your post you define cache_email_sent_list() as a function defined in a class definition, which will not work. I think you are confusing instance methods, static methods and functions. There's a prominent difference between these three.
So, as a stylised example:
# instance method:
class MyClass(MySuperClass):
def my_instance_method(self):
#your code here
# call the instance method:
instance = MyClass() # creates a new instance
instance.my_instance_method() # calls the method on the instance
# static method:
class MyClass(MySuperClass):
#staticmethod # use decorator to nominate a static method
def my_static_method()
#your code here
# call the static method:
MyClass.my_static_method() # calls the static method
# function
def my_function():
# your code here
# call the function:
my_function() # calls your function
Indentation is part of Python syntax and determines how the interpreter handles your code. It takes a bit getting used to but once you've got the hang of it, it's actually really handy and makes your code very readable. I think you have an indentation error in your original post. Just add the correct indentation for the method cache_email_sent_list() and call it on an instance of EmailMessageHandler and you're good to go.
The problem has nothing to do with GAE.
The problem is that you've defined cache_email_sent_list as a method of the class EmailMessageHandler, but you're trying to call it as a top-level function. You can't do that. You need to have an instance of a EmailMessageHandler to call it on.
If you're trying to call it from another method of EmailMessageHandler, that instance should be available as self. For example:
self.cache_email_sent_list()
If you're trying to call it from elsewhere, it's up to you to figure out what instance you should be calling it on. For example:
handler_passed_as_param_to_this_function.cache_email_sent_list()
Note that your error message is about cache_email_received_list, but your code only has cache_email_sent_list. I'm guessing that you have parallel code, and the exact same error for both cases, but of course I could be guessing wrong—in which case you'll have to actually show us either the code that goes with your displayed error, or the error that goes with your displayed code…
Related
I have a method in my model that I would like to call in my views. However, I get a NameError that this function is not defined (I have imported all models in my views and all migrations are up to date). It has worked for other functions in the past.
Here is my model:
class Song(models.Model):
"""
fields
"""
def lyrics_as_list(self):
return self.lyrics_ru.split()
def sorted_strings(self, strings, locale=None):
if locale is None:
return sorted(strings)
collator = icu.Collator.createInstance(icu.Locale(locale))
return sorted(strings, key=collator.getSortKey)
And in my views the relevant part where I want to use it:
lyrics_list = models.Song.objects.get(pk=self.kwargs['pk']).lyrics_as_list() #this is also a method on my model, and it does work
lyrics_sorted = sorted_strings(set(lyrics_list, "ru_RU.UTF8")) #but this one gives me an error
The error: name 'sorted_strings' is not defined
When I move the method to my views, it works. But I have to use this in several views, so I am trying to follow the DRY principle, and so it would be great to get it to work.
Edit - What the sorted_strings function is for:
My Song model contains lyrics. I am displaying all words in the lyrics in a table, but I want to show it alphabetically. In order to be able to sort Russian words, I needed to add this function.
The method sorted strings as defined in the class Song:
class Song(models.Model):
"""
fields
"""
def sorted_strings(self, strings, locale=None):
if locale is None:
return sorted(strings)
collator = icu.Collator.createInstance(icu.Locale(locale))
return sorted(strings, key=collator.getSortKey)
cannot be called like this:
sorted_strings(strings, locale)
This obviously leads to a NameError. It is a method, so you need to call it on an object as instance of that class.
You might get tempted to try this:
Song.sorted_strigns(strings, locale)
but it won't work. It will result in missing 1 required positional argument. That is you have to provide self. You can't call it directly on the class.
If you introspect this method well, it doesn't perform any action on an object. The argument self is not used. You'd like to call it without instantiating an object, but directly on the class. Therefore you can use the decorator #staticmethod:
#staticmethod
def sorted_strings(strings, locale=None):
if locale is None:
return sorted(strings)
collator = icu.Collator.createInstance(icu.Locale(locale))
return sorted(strings, key=collator.getSortKey)
Please notice how the static method doesn't need to be passed the argument self.
Now your code should work like this:
lyrics_list = Song.objects.get(pk=self.kwargs['pk']).lyrics_as_list()
lyrics_sorted = Song.sorted_strings(set(lyrics_list), "ru_RU.UTF8")
Also in your code example you have an error with the parentheses in the second line.
Besides static methods, there are also class methods, defined using the decorator #classmethod. For this purpose here I'd go with the static method, but if someone has an objection, I'm ready to learn.
Static methods are not very common in Python and frowned upon by many.
Nevertheless it's good to know they exist and how they work.
lyrics_list = models.Song.objects.get(pk=self.kwargs['pk']).lyrics_as_list()
lyrics_sorted = models.Song.objects.sorted_strings(set(lyrics_list), "ru_RU.UTF8")
Manager's method can only be called with Model.objects
DJANGO APP
I have interface for sending e-mail in Django:
from my_app.utils import com
com.mail.email_category1(subject, template, ...)
...
com.mail.email_category2(subject, template, ...)
I have also another interafces for ie. for SMS:
com.sms.sms_category1(template, ...)
In my_app.utils.com there are functions defined:
# my_app.utils.com
mail = CommunicationMail()
sms = CommunicationSms()
...
and categories are methods of above classes.
QUESTION
Is it possible to call new instance of CommunicationMail every time I call com.mail.email_category...? The problem is that it is the same object instance every call, so ie. when running in parallel as a task, they share properties and overlaps.
This would be the recommended structure:
from my_app.utils import com
com.Mail().email_category1(template, ...)
where my_app.utils.com is:
Mail = CommunicationMail
If you really wanted to keep the com.mail.email_category1 notation, Python would let you, of course, being the dynamic language that it is
(__getattr__ documentation):
# my_app.utils.com
class CommunicationMailFactory:
def __getattr__(self, name):
instance = CommunicationMail()
return getattr(instance, name)
mail = CommunicationMailFactory()
But use the first method! “Why,” you ask.
For one, it is makes it clear what you are doing: You are instantiating a new instance and calling a method. This is not clear with the __getattr__ hackery.
Second, you can assign the freshly instantiated instance to a variable mail1 and then call mail1.email_category1(subject, template, ...) or whatever. You have no such normal, expected flexibility with the __getattr__ hackery.
Python modules are singleton, so it will only import it once, so mail = CommunicationMail() is executed once.
you can:
from my_app.utils import com
com.CommunicationSms().sms_category1(template, ...)
name_player = None
health_player = None
inventory_player = []
class engine:
print name_player
I have no idea why this runs without calling it with engine()
The Python interpreter starts by reading your file, one line at a time.
Step 1:
name_player = None adds name_player : None to locals()
Step 2 and 3 proceed in the same way.
Step 4: class engine: Python sees a class and prepares to load the definition into memory. So it's going to read the class and put all of the fields and method definitions into some runtime dictionary probably. In order to do that, it needs to execute the statements in the class.
So normally a class might look like
class Foo():
def my_method():
return "I'm foo!"
This would define a method, and put that definition with the class definition on the heap.
So your definition proceeds as follows. We've started creating the class object and then we come across a statement, so the interpreter executes it. In your case, it's a print statement, so you see it executed.
You'll see now if you call engine(), another print won't happen.
What you probably want is to have this statement in a constructor like so:
class engine:
def __init__(self); #__init__() is a constructor in Python
print name_player
For more information about classes in Python, see https://docs.python.org/2/tutorial/classes.html
When you define a class, python evaluates the statements making up the class's definition. If those statements have side effects, for example sending text to the standard output, then that text will get sent.
If you were to instantiate this, by calling engine(), you would get back an empty object.
I want to send a session object of sqlalchemy to a function of another class .
From class OraDialog's function oraconnect to class oraconn's assign function .
Actually My need is to use the session object in oraconn's another function map
I can't send the session object directly to map function because it is a slot - it is triggered before .
I intended to define the assign function primarily to get the session object.
The Error : ( including print statements )
<sqlalchemy.orm.session.Session object at 0x030808F0>
<sqlalchemy.orm.session.Session object at 0x030808F0>
This is in assign
None
This is in map
Traceback (most recent call last):
File "C:\Users\Arul\Desktop\dbvis\oraconn.py", line 44, in map
for t in self.s.query(tables):
AttributeError: 'NoneType' object has no attribute 'query'
The oraconn class's assign and map functions :
def assign(self,s):
self.s=s
print self.s
print "This is in assign"
def map(self):
print self.s
print "This is in map"
self.table_no=0
for t in self.s.query(tables):
self.table_no=self.table_no+1
table_list.append(t.table_name)
self.item=QtCore.QStringList()
for c in self.s.query(columns):
self.item.append(c.column_name)
self.ui.list_col.addItems(self.item)
SO ,
The assign function receives the object properly . But the map function can't use it - It says Nonetype
My Question :
Two functions of same class can't use an object ?
I must have done something silly - so plz point out......
( I'm using windows7 / python 2.6 / PyQt4 /sqlalchemy /cx_oracle)
Edit :
The calling class :
class OraDialog(QtGui.QDialog):
def __init__(self,parent=None):
QtGui.QDialog.__init__(self,parent)
self.odia=Ui_Dialog()
self.odia.setupUi(self)
self.uiobj=oraconn()
QtCore.QObject.connect(self.odia.but_con,QtCore.SIGNAL('clicked()'),self.uiobj.oraconnect)
def oraconnect(self):
self.setVisible(0)
eng_str="oracle://"+self.odia.line_user.text()+":"+self.odia.line_pass.text()+"#localhost:1521/"+self.odia.line_sid.text()+"?mode="+self.odia.line_role.text()
engine_str=str(eng_str)
engine=create_engine(engine_str)
Session=sessionmaker(engine)
self.s=Session()
print self.s
Problem Solved :
The problem is - i've created two instances and passed from one to another .
Corrected code :
oraconn.assign(myapp,self.s)
where
oraconn -> class
assign -> function of oraconn
myapp -> instance of oraconn , declared for main application
self.s -> the argument i wanted to pass
Thank you Kirk ....
If you're using Qt, then this is likely a GUI app. Maybe there are threading issues; maybe self refers to different objects. It's hard to tell with only what you've given us. Before you go any further, add:
print self
near the top of each method. At least then you can confirm whether both are operating on the same object.
In OraDialog.init, you're saying self.uiobj=oraconn(). Is that the object that's giving you problems? If so: notice that you're creating at as an instance variable, so that each OraDialog object has a different .uiobj object. Could you try making that a class variable by writing:
class OraDialog(QtGui.QDialog):
uiobj = oraconn()
def __init__() [...]
instead? That is, define uiobj as belonging to all instances of the class, not just one instance.
The code you have posted seems to be okay, I can't spot any obvious mistakes.
The problem must be on the calling side. As the self reference can be passed explicitly to methods (via OraDialog.map(my_object), where my_object could be anything) this perfectly possible. Also note that this has nothing to do with scoping.
You should check calling code of the map function. It is very likely it is called on a different object as assign.
I have something like that in my python code
class A:
__mess = "Yeap!"
def doSome(self):
self.FN()
def FN(self):
pass
def myFN(self):
print self.__mess
b = A()
b.FN = myFN
b.doSome()
But this doesn't work. Where am I wrong?
python 2.6.5
upd: I want to redefine method (FN) only for one exemplar (b).
upd2:
import new
class A:
__mess = "Yeap!"
def doSome(self):
self.FN()
def FN(self):
pass
def myFN(self):
print self.__mess
b = A()
b.FN = new.instancemethod(myFN, b, A)
b.doSome()
Doesn't work too.
Traceback (most recent call last):
File "", line 1, in
File "", line 4, in doSome
File "", line 2, in myFN
AttributeError: A instance has no
attribute '__mess'
myLoopFN is a function, not an instance method. Do
import new
b.loopFN = new.instancemethod( myLoopFN, b, A )
The problem is that Python treats instance methods very slightly differently to regular functions: they get the instance upon which they are run as the default first argument. If you define a method inside a class definition it automagically becomes an instance method, so that when you instantiate the class it gets passed the instance. However, when you define myLoopFN you do it outside the class definition, so that it is an ordinary function instead of an instance method. You fix this by explicitly declaring it as an instance method.
...
BUT
This is icky because it's not something you should do; changing instance methods at runtime will lead to problems. You'll never be sure whether your A is an original A or a modified one, and you won't be able to debug it because you can't tell whether you've changed loopFN or not. This will give you the kind of bugs that Nyarlathotep himself would be proud of.
The right way to do this is to subclass A and override the method, so that you can distinguish between the different classes.
class myA( A ):
def loopFN(self):
#put modified function here
This way, you can instantiate the modified class and be certain of its methods.
Edit
You are using a double-underscore variable name, __mess. You (almost certainly) don't want to do this. For some reason known only to our Benevolent Dictator for Life and a select few others, Python automatically mangles these __ names to _<class-name>__, to serve as a sort-of faux private variable. This is horrible, and besides there's no reason to call it __mess instead of (the much nicer) mess.
If you absolutely must call it __mess, you can refer to it as follows:
def myFN(self):
print( self._A__mess )
(mutatis mutandis when you change the name of A). This is nasty and unPythonic.
Regarding the second error (with __mess):
Change
print self.__mess
to
print self._mess
And change
class A:
__mess = "Yeap!"
to
class A:
_mess = "Yeap!"
Double underscores tell Python to use name-mangling.
An alternative is to change
def myFN(self):
print self.__mess
to
def myFN(self):
print self._A__mess