I want to have a timeout for a function (rest API call) in python & for that I am following this SO answer.
I already have one existing code structure where i want to have a timeout decorator. I am defining a timeout seconds in ".txt" file & passing it as a dict to main function. Something like :
class Foo():
def __init__(self, params):
self.timeout=params.get['timeout']
....
....
#timeout(self.timeout) #throws an error
def bar(arg1,arg2,arg3,argn):
pass
#handle timeout for this function by getting timeout from __init__
#As answer given in SO ,
#I need to use the self.timeout, which is throwing an error:
***signal.alarm(seconds)
TypeError: an integer is required***
#And also
***#timeout(self.timeout)
NameError: name 'self' is not defined***
#timeout(30) #Works fine without any issue
def foo_bar(arg1,arg2,arg3,argn):
pass
What am i missing ?
At A the self is not defined because the decorator is outside the method, but self only exists inside the method:
#timeout(self.timeout) # <== A
def bar(self,arg1,arg2,arg3):
pass
You can try to set the barTimeout attribute at __init__:
class Foo():
def bar(self,arg1,arg2,arg3):
pass
def __init__(self, params):
self.timeout=params.get('timeout')
self.barTimeout = timeout(self.timeout)(self.bar)
Foo({'timeout':30}).barTimeout(1,2,3)
Related
This question already has answers here:
"TypeError: method() takes 1 positional argument but 2 were given" but I only passed one
(10 answers)
Closed 8 months ago.
I'm trying to implement a subclass and it throws the error:
TypeError: worker() takes 0 positional arguments but 1 was given
class KeyStatisticCollection(DataDownloadUtilities.DataDownloadCollection):
def GenerateAddressStrings(self):
pass
def worker():
pass
def DownloadProc(self):
pass
Your worker method needs 'self' as a parameter, since it is a class method and not a function. Adding that should make it work fine.
If the method doesn't require self as an argument, you can use the #staticmethod decorator to avoid the error:
class KeyStatisticCollection(DataDownloadUtilities.DataDownloadCollection):
def GenerateAddressStrings(self):
pass
#staticmethod
def worker():
pass
def DownloadProc(self):
pass
See https://docs.python.org/3/library/functions.html#staticmethod
You forgot to add self as a parameter to the function worker() in the class KeyStatisticCollection.
This can be confusing especially when you are not passing any argument to the method. So what gives?
When you call a method on a class (such as work() in this case), Python automatically passes self as the first argument.
Lets read that one more time:
When you call a method on a class (such as work() in this case), Python automatically passes self as the first argument
So here Python is saying, hey I can see that work() takes 0 positional arguments (because you have nothing inside the parenthesis) but you know that the self argument is still being passed automatically when the method is called. So you better fix this and put that self keyword back in.
Adding self should resolve the problem. work(self)
class KeyStatisticCollection(DataDownloadUtilities.DataDownloadCollection):
def GenerateAddressStrings(self):
pass
def worker(self):
pass
def DownloadProc(self):
pass
class KeyStatisticCollection(DataDownloadUtilities.DataDownloadCollection):
def GenerateAddressStrings(self):
pass
def worker(self):
pass
def DownloadProc(self):
pass
I get this error whenever I mistakenly create a Python class using def instead of class:
def Foo():
def __init__(self, x):
self.x = x
# python thinks we're calling a function Foo which takes 0 args
a = Foo(x)
TypeError: Foo() takes 0 positional arguments but 1 was given
Oops!
Check if from method with name method_a() you call method with the same name method_a(with_params) causing recursion
just pass self keyword in def worker(): function
class KeyStatisticCollection(DataDownloadUtilities.DataDownloadCollection):
def GenerateAddressStrings(self):
pass
def worker(self):
pass
def DownloadProc(self):
pass
another use case for this error is when you import functions within the class definition. this makes the subsequent function calls a part of the class object. In this case you can use #staticmethod on the library import function or make a static path call directly to the function. see example below
In this example "self.bar()" will throw a TypeError, but it can be fixed in two ways
# in lib.py
def bar():
print('something to do')
# in foo.py
class foo():
from .lib import bar
def __init__(self):
self.bar()
Option 1:
# in lib.py
def bar():
print('something to do')
# in foo.py
class foo():
from .lib import bar
def __init__(self):
lib.bar()
Option 2:
# in lib.py:
#staticmethod
def bar():
print('something to do')
# in foo.py
class foo():
from .lib import bar
def __init__(self):
self.bar()
When doing Flask Basic auth I got this error and then I realized I had wrapped_view(**kwargs) and it worked after changing it to wrapped_view(*args, **kwargs).
class KeyStatisticCollection():
def GenerateAddressStrings(self):
pass
def worker():
return blabla
def DownloadProc(self):
abc = self.GenerateAddressStrings()
#abc = GenerateAddressStrings()#error
blabla = worker()
#blabla = self.worker()#error
i think this is a better explaination about using self param
Background
In python mocking, there is a function assert_has_calls which can verify the order of arguments used to call a function. It has a helper object call which helps validate the arguments.
Problem
Using call(), you cannot pass self as a kwarg. It gives the error: TypeError: __call__() got multiple values for argument 'self'. Why? The workaround is to simply not use self as a kwarg, but I'm afraid there's something fundamental I'm misunderstanding and can't find anything in the documentation that points to it.
Live Code
The code below is pasted here for you to play with: https://repl.it/#artoonie/ObviousIntentReality#main.py
Pasted Code
File 1: test_class.py
needs to be a separate file for mock.patch decorator discoverability
class Class:
def func(self, num):
return num
class Runner:
def run(self):
return Class().func(1)
File 2: test.py
import mock
import test_class
unmockedFunction = test_class.Class.func
class Test:
#mock.patch('test_class.Class.func', autospec=True)
def test_me(self, mocker):
# Make the mock do nothing
mocker.side_effect = unmockedFunction
# Run the function
test_class.Runner().run()
# This works
mocker.assert_called_with(self=mock.ANY, num=1)
# This works
mocker.assert_has_calls([
mock.call(mock.ANY, num=1)
])
# This fails
mocker.assert_has_calls([
mock.call(self=mock.ANY, num=1)
])
Test().test_me()
I have the following code:
A decorator:
def pyDecorator(func):
print func
#wraps(func)
def wrapped(*args, **kwargs):
print args
print kwargs
tBegin = time()
result = func(*args, **kwargs)
tEnd = time()
if result:
# UI update
print("\nTBegin '{}'({} s)".format(func.__name__, tBegin))
# UI and report update
print("TEnd '{}' ({} s) ({} s) Result:{}".format(func.__name__, tEnd,tEnd - tBegin, result))
return result
#workarround to use the original function
wrapped._original=func
return wrapped
And a decorated class method:
class Dummy(object):
#pyDecorator
def ClassMethod(self):
print "Original class code executed"
return True
If I call the method for the original function in the following way, I receive this error "TypeError: ClassMethod() takes exactly 1 argument (0 given):"
ClassInstance.ClassMethod._original()
So I am forced to use the following call:
ClassInstance.ClassMethod._original(ClassInstance)
Is it possible to do this as in the first way ? I do not understand why I should put the class instance as a parameter when it is already provided.
ClassInstance.ClassMethod._original is a function not bound to any class instance.
Note that the transformation from function to method happens when a function object is accessed via a class instance, say, using dot reference. Here however, _original is only bound to another function object wrapper (elevated to a bound method at runtime) not to a class instance. An implicit self parameter is therefore not passed. You'll have to explicitly pass it.
ClassInstance.ClassMethod._original
^
|- instance ^
|- method
^
|- function object bound to method
I do not understand why I should put the class instance as a parameter
when it is already provided
No, it's not already provided.
I'm trying to override the DaemonRunner in the python standard daemon process library (found here https://pypi.python.org/pypi/python-daemon/)
The DaemonRunner responds to command line arguments for start, stop, and restart, but I want to add a fourth option for status.
The class I want to override looks something like this:
class DaemonRunner(object):
def _start(self):
...etc
action_funcs = {'start': _start}
I've tried to override it like this:
class StatusDaemonRunner(DaemonRunner):
def _status(self):
...
DaemonRunner.action_funcs['status'] = _status
This works to some extent, but the problem is that every instance of DaemonRunner now have the new behaviour. Is it possible to override it without modifying every instance of DaemonRunner?
I would override action_functs to make it a non-static member of class StatusDaemonRunner(DaemonRunner).
In terms of code I would do:
class StatusDaemonRunner(runner.DaemonRunner):
def __init__(self, app):
self.action_funcs = runner.DaemonRunner.action_funcs.copy()
self.action_funcs['status'] = StatusDaemonRunner._status
super(StatusDaemonRunner, self).__init__(app)
def _status(self):
pass # do your stuff
Indeed, if we look at the getter in the implementation of DaemonRunner (here) we can see that it acess the attribute using self
def _get_action_func(self):
""" Return the function for the specified action.
Raises ``DaemonRunnerInvalidActionError`` if the action is
unknown.
"""
try:
func = self.action_funcs[self.action]
except KeyError:
raise DaemonRunnerInvalidActionError(
u"Unknown action: %(action)r" % vars(self))
return func
Hence the previous code should do the trick.
This question already has answers here:
"TypeError: method() takes 1 positional argument but 2 were given" but I only passed one
(10 answers)
Closed 8 months ago.
I'm trying to implement a subclass and it throws the error:
TypeError: worker() takes 0 positional arguments but 1 was given
class KeyStatisticCollection(DataDownloadUtilities.DataDownloadCollection):
def GenerateAddressStrings(self):
pass
def worker():
pass
def DownloadProc(self):
pass
Your worker method needs 'self' as a parameter, since it is a class method and not a function. Adding that should make it work fine.
If the method doesn't require self as an argument, you can use the #staticmethod decorator to avoid the error:
class KeyStatisticCollection(DataDownloadUtilities.DataDownloadCollection):
def GenerateAddressStrings(self):
pass
#staticmethod
def worker():
pass
def DownloadProc(self):
pass
See https://docs.python.org/3/library/functions.html#staticmethod
You forgot to add self as a parameter to the function worker() in the class KeyStatisticCollection.
This can be confusing especially when you are not passing any argument to the method. So what gives?
When you call a method on a class (such as work() in this case), Python automatically passes self as the first argument.
Lets read that one more time:
When you call a method on a class (such as work() in this case), Python automatically passes self as the first argument
So here Python is saying, hey I can see that work() takes 0 positional arguments (because you have nothing inside the parenthesis) but you know that the self argument is still being passed automatically when the method is called. So you better fix this and put that self keyword back in.
Adding self should resolve the problem. work(self)
class KeyStatisticCollection(DataDownloadUtilities.DataDownloadCollection):
def GenerateAddressStrings(self):
pass
def worker(self):
pass
def DownloadProc(self):
pass
class KeyStatisticCollection(DataDownloadUtilities.DataDownloadCollection):
def GenerateAddressStrings(self):
pass
def worker(self):
pass
def DownloadProc(self):
pass
I get this error whenever I mistakenly create a Python class using def instead of class:
def Foo():
def __init__(self, x):
self.x = x
# python thinks we're calling a function Foo which takes 0 args
a = Foo(x)
TypeError: Foo() takes 0 positional arguments but 1 was given
Oops!
Check if from method with name method_a() you call method with the same name method_a(with_params) causing recursion
just pass self keyword in def worker(): function
class KeyStatisticCollection(DataDownloadUtilities.DataDownloadCollection):
def GenerateAddressStrings(self):
pass
def worker(self):
pass
def DownloadProc(self):
pass
another use case for this error is when you import functions within the class definition. this makes the subsequent function calls a part of the class object. In this case you can use #staticmethod on the library import function or make a static path call directly to the function. see example below
In this example "self.bar()" will throw a TypeError, but it can be fixed in two ways
# in lib.py
def bar():
print('something to do')
# in foo.py
class foo():
from .lib import bar
def __init__(self):
self.bar()
Option 1:
# in lib.py
def bar():
print('something to do')
# in foo.py
class foo():
from .lib import bar
def __init__(self):
lib.bar()
Option 2:
# in lib.py:
#staticmethod
def bar():
print('something to do')
# in foo.py
class foo():
from .lib import bar
def __init__(self):
self.bar()
When doing Flask Basic auth I got this error and then I realized I had wrapped_view(**kwargs) and it worked after changing it to wrapped_view(*args, **kwargs).
class KeyStatisticCollection():
def GenerateAddressStrings(self):
pass
def worker():
return blabla
def DownloadProc(self):
abc = self.GenerateAddressStrings()
#abc = GenerateAddressStrings()#error
blabla = worker()
#blabla = self.worker()#error
i think this is a better explaination about using self param