self parameter error celery - python

I saw some blogs online where they put self parameters on their celery functions, why is mine causing an error like:
TypeError: xml_gr() takes exactly 1 argument (0 given)
Here is my code:
#periodic_task(run_every=timedelta(seconds=5))
def xml_gr(self):
ftp = FTP('xxxxx')
ftp.login(user='xxxxx', passwd='xxxxx')
x = xml_operation('AGIN', GR_GLOBAL_CURRENT_DATE, ftp, "GR")
ftp.close()

In addition to the accepted answer, self is used in celery to bind tasks.
Bound tasks are needed for retries. for accessing information about
the current task request, and for any additional functionality
you add to custom task base classes.
So, if you specify #task(bind=True) then you need add self as the first argument. Otherwise, not needed.
Source

"self" is used within class member functions. When you call a member function in an instance of the class, the language automatically passes in the class instance as "self". "self" lets you access the members of the class.
class Thing:
var1 = None
def set_member(self, value):
self.var1 = value
def show_member(self, value):
return self.var1
Then usage would be
a = Thing()
a.set_member(23)
a.show_member()
And you'd see the response 23. You don't have to pass in the "self" variable explicitly.
When you declare functions outside of a class, there is no reason to use "self".

Related

default arg with test class member variable

Have the simplified script snippet as follows:
#!pytest
import pytest
class TestDefaultArg():
#pytest.fixture(scope="class", autouse=True)
def setup_cleanup(self, request):
request.cls.default_id = 100
yield
def test_basic(self):
self.db_helper()
def db_helper(self, id=self.default_id):
pass
The intention is to pass the class memeber self.default_id to db_helper(). However, it gives me this error:
/u/qxu/test.py:4: in <module>
class TestDefaultArg():
/u/qxu/test.py:13: in TestDefaultArg
def db_helper(self, id=self.default_id):
E NameError: name 'self' is not defined
So, the question is, how to use a test class data member to provide the default argument for a test class member function?
This is not related to pytest, but just to normal Python functionality.
You cannot reference self in a default argument, because the default argument is created at load time, not at run time. Also, you have been creating a class variable, not an instance variable, so you have to access it using self.__class__ instead of self.
The usual way to handle this is to use a None default value and only set the value in the function, e.g. something like:
def db_helper(self, current_id=None):
if current_id is None:
current_id = self.__class__.default_id
print(current_id)
Note that I have also changed the variable name, as id is a built-in name, and it is not good practice to shadow these.
EDIT: Use check for None as proposed by #chepner.

Variable assignment in the constructor

I have a question to the variable assignment in the constructor: I have a constructer which takes the argument 'context'. First, I assign this variable to a class variable. Second, I create another class which also takes 'context' as an argument.
To my question: Is it better to assignment the class variable (self.context) or the argument from the constructor (context) to the new created class?
class State():
def __init__(self, context):
self.context = context
self.diconnected = Disconnected(self.context)
or
class State():
def __init__(self, context):
self.context = context
self.diconnected = Disconnected(context)
The end result is the same. Disconnected(context) is just slightly shorter and faster.
This is really not going to effect your program execution time in any significant way in Python. The only situation this could matter is when multiple threads may be using this data. I'd always use the argument just in case.
None is objectively "better"; you're passing the same object to Disconnected in any case.
Which one you write depends on which dependency you want to emphasize: that Disconnected has the same context as self (which also implies that self always has one), or that it has the context passed in as the parameter.

Can Python Staticmethod Call Another Local Method?

In Python, within a class, can a staticmethod call on another local function/method defined within the same class?
I tried the following code and obtained an error message saying foo1() is not defined.
class trialOne(object):
#staticmethod
def foo1():
a = 3.1
return a
#staticmethod
def foo():
a = foo1()
return a
obj = trialOne()
b = obj.foo()
class Tester:
def local(self):
print "I'm a local!"
#staticmethod
def another_stat():
print "I'm a static!"
#staticmethod
def stat(inst):
inst.local()
Tester.another_stat()
t = Tester()
Tester.stat(t)
# Out:
# I'm a local!
# I'm a static!
Yes, you can! By definition, instance methods need an instance to associate themselves with, but as long as you have that instance, you can call local methods just as you normally would.
To go into this in a little more depth, there's nothing special about the word self. That's a variable just like any other. Any instance method of a class MUST take in an instance of that class as its first parameter, and it's convention to call that parameter self, but you could just as easily use any other name.
If it helps you understand the distinction, these two statements are semantically equivalent:
t.local()
Tester.local(t)
The first is just syntactic sugar for the second. The second is using the class name to reference a method of the Tester class, then passes in the instance as the first parameter. The first simply pretends that local is a field of t and calls it, but that call is transformed into Tester.local(t) by the Python interpreter.
Thus, calling a static method is the same syntax as Tester.local(t), except the first parameter does not have to be an instance of that class.
So classmethods and staticmethods are called in the same way, but the difference is that a class method "knows" what class it's coming from. The first parameter of a class method is always a variable that contains the class that it's being invoked from. That way if the method is inherited, it knows which method it's coming from, where a staticmethod would not know. In your comment, you said this:
#classmethod
def stat(cls):
cls.another_stat()
In this example, cls is a variable that contains the class that the method is being called from, not an instance of the class that it is being called from. That is why you can call static methods with cls - because it is equivalent to Tester

How to make user defined classes in web2py

I am trying to make a class within a module, import that module file in my controller, and then reference the class that is defined within that module, but I keep getting a message that reads NameError("name 'self' is not defined")
Here is my code in my created module:
from gluon import *
class device_info(object):
self.info = {}
def __init__(self, info):
self.info = info
return
def setInfo(info):
self.info = info
return
def getInfo():
return self.info`
Does anyone know what causes this and how it can be resolved? I was under the impression that user-defined classes were supported in web2py.
As stated, just move self.info = {} into __init__().
__init__() is essentially a constructor that you are familiar with from java. It initializes an instance object of that class when called. I haven't used Java in some time, but I don't think you should be be declaring class variables outside of your constructor there either.
self is an argument that all methods within a class in python must receive as their first argument. So your getters and setters are also not going to work if you try them; they must be:
def setInfo(self, info) and def getInfo(self)
When you create an object, like this:
device1 = device_info()
it calls __init()__, passing device1 as self. Then, whenever you use that object, such as
device1.setInfo(newInfo), you can think of the method in the class' context being called as setInfo(device1, newInfo), since device1 is self, or the current instance of the device_info object in use.
You also don't need the object argument at the class definition. What do you expect that to do?
Edit: Actually, don't move self.info = {} into __init__(), just get rid of it. You already have self.info = info in __init__(). You don't need to initialize variables like that in Python like you do in Java. Creating an empty dict and then setting it to another dict without any use is redundant.

passing self to a function

This code is inside a class. I need to access variables defined in the classe's self. How could I pass self to the entry_deletion_images_delete ?
#receiver(pre_delete, sender=Document, dispatch_uid='document_delete_signal')
def entry_deletion_images_delete(sender, instance, using, **kwargs):
for key, value in self.SIZES.items():
os.remove(self.base_dir + instance.image_main.name)
Since this function uses built in arguments, simply putting self as a new argument is not possible.
You are passing to #receiver() an unbound function. You should pass it a bound method, like this:
class MyClass(object):
def entry_deletion_images_delete(self, sender, instance, using, **kwargs):
...
instance = MyClass()
pre_delete.connect(instance.entry_deletion_images_delete, sender=Document, dispatch_uid='document_delete_signal')
In other words, first you have to create an instance (otherwise what would self be?), then you can register the instance method as a receiver for the signal.
What I have shown is just an example. How to actually create the instance and when to connect the receiver depends on your use case.

Categories