publish() takes at least 3 arguments (3 given) - python

I am working with ceilometer python API and publishing data to pubnub. not sure what is meant by this error.
This is the part of code that is causing the problem i think,
def init_Data(data, channel):
cpu_sample = cclient.samples.list(meter_name ='cpu_util')
for each in cpu_sample:
timetamp = each.timestamp
volume = each.counter_volume
volume_int = int(volume)
data_volume ={'value': volume_int}
data=json.dumps(data_volume)
print (data)
pubnub.publish(channel='orbit_channel', callback= init_Datar)

publish() takes at least 3 arguments (3 given)
Such a terrible error message! One point of confusion is that self is also counted as an argument, even if it's not explicitly provided.
So you need to provide 2 arguments. And you did! But you need to provide the 2 required arguments, while you only provided 1 required and 1 optional argument. Check the API docs for pubnub.publish() to see what you're missing.

While Daniel provided a good explanation, I wanted a minimalist example and was able to come up with this:
>>> class Foo(object):
... def __init__(self, arg1, arg2=None):
... pass
...
>>> Foo(arg2=1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __init__() takes at least 2 arguments (2 given)
So two arguments are provided (self and arg2), but it's saying at least 2 positional arguments are required (self and arg1). So Foo(arg1=1) would work, as would Foo(1, 2) and Foo(1, arg2=2).

Related

Design a function so that it can be used as CLI (using click) and python modules directly

I am searching a design through which same python function can be exposed to other modules as well as a CLI created using click module.
I saw many posts available for the same but my requirement is little different.
I have a command as:
#click.command()
#click.option('--times', default=10)
def print_hello(times):
_print_hello(times)
def _print_hello(times):
pass
Here main logic to print something is written in _print_hello function which is fine.
If I wanted to call print_hello method from a function defined in other modules then it would be a hectic task for the caller.
Do we have any easy way or good pattern because I have more than 20 CLI APIs which I need to expose as python API as well?
Do you mean, how to make a function accept one or more arguments ? Give each argument a default value:
def print_func(param1, param2=None, param3=None, param4=None, param5=None):
print(param1, param2, param3, param4, param5)
print_func()
print_func(1)
print_func(1, 2)
print_func(1, 2, 3, 4, 5)
Output:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: print_func() missing 1 required positional argument: 'param1'
1 None None None None
1 2 None None None
1 2 3 4 5

Double check about Arbitrary Keyword Arguments in Python

I'm quite new to Python and I'm studing an opensource framework written in Python. I'm trying to dive a little bit deeper in the source code. I can't understand why the "Arbitrary Arguments" and "Arbitrary Keyword Arguments" are required in this line of code:
observerCallback = lambda *args, **kwargs: self.pushRender(realViewId)
basically because, at the end, they are not used in the "called" method:
def pushRender(self, vId, ignoreAnimation = False):
...
So, once again: what is the purpose of using *args and **kwargs here? I know it could looks like a silly question, but I just learnt right now meaning of this "special operators" and my brain is almost out of work after days spent on exploring this source code. If someone can help me understand a little bit better, for sure I really appreciate that.
The caller of observerCallback is probably passing some arguments to the function, so the function needs to accept them. Otherwise this would happen:
>>> observerCallback = lambda: self.pushRender(realViewId)
>>> observerCallback('foo', bar='baz')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: <lambda>() got an unexpected keyword argument 'bar'
This particular observerCallback simply chooses to ignore/not use any passed arguments. By convention you should use _ instead of "args" and "kwargs" as an indicator that you're going to disregard those arguments:
lambda *_, **__: ...

weird * in function definition [duplicate]

This question already has answers here:
Bare asterisk in function parameters?
(6 answers)
Closed 4 years ago.
I met a weird case in the function definition in python, I read some code like this:
def abc(dd, *, ee=None):
print(dd, ee)
In the beginning, I thought this code is wrong and maybe a typo of *args, but recently I tried this code in latest python3.7, and it seems that it can be interpreted, and usage is also super wired, you can't pass more than 1 argument to this function:
>>> abc(11, 222)
Traceback (most recent call last):
File "<input>", line 1, in <module>
abc(11, 222)
TypeError: abc() takes 1 positional argument but 2 were given
>>> abc(11)
11 None
I am asking because I don't know the purpose of why some one wrote like this, and why python support this behaviour in Python3(not supported in python2)
It seems your function has 1 positional argument and one named argument. The * eats all other positional arguments, just like an *args would, but you cannot reference them.

Return function arguments in TypeError when number of arguments are not met

I have been creating my own python file in which I create functions that I can call upon when plotting. This way I only have to load in one file with all kinds of functions that I can use to tweak my results, keeping my code simple.
What I want to know is whether it is possible to return which arguments a function is missing and if so how to implement this?
To illustrate what I mean, I define the following function:
def func(integer, float):
return integer / float
If I now would call the function like:
print func(2)
it will give the error which states it requires two arguments and one is missing.
TypeError: func() takes exactly 2 arguments (1 given)
Since I will be expanding my tweak file over the years I will be forgetting some of the functions and the required arguments. Therefore I would like to be returned an error which states the names of the arguments.
So in the case of the example I would like to be returned something like:
TypeError: func(integer, float) takes exactly 2 arguments (1 given)
I don't even really care about the number of arguments that are required or are given. All I really need is just func(integer, float) in the case I am missing an argument or giving one too many.
Is this possible?
Thanks in advance!
I don't think you would ever want to really do this - but I guess one hacky approach would be use getargspec() from the inspect module to determine the "names and default values of a Python function’s arguments.", and then wrap all function calls in try/except blocks.
>>> try:
func(2):
except TypeError as e:
print "Error! The function expected {} args".format(getargspec(func).args)
raise e
Error! The function expected ['integer', 'float'] args
Traceback (most recent call last):
File "<input>", line 5, in <module>
TypeError: func() takes exactly 2 arguments (1 given)
You could maybe wrap that into a custom exception too, which subclasses TypeError (although here we are assuming that the TypeError is being raised because the function wasn't passed the correct number of arguments which might be a bit of an over-simplification).
Note that you can't add code to do this inside the function object itself, as Python raises the TypeError exception before it executes any of the code in the function body.
>>> def another_func(arg1):
print "Got inside the function - the arg was {}".format(arg1)
>>> another_func("hello")
Got inside the function - the arg was hello
>>> another_func()
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: another_function() takes exactly 1 argument (0 given)
I finally managed to write this code, I hope it helps:
import inspect, traceback
def func(integer, float):
return integer / float
if __name__ == "__main__":
try:
func(2)
except TypeError:
print "ERROR: 'func(a, b)' . a is an integer and b is a float"
print traceback.format_exc()
Output:
ERROR: 'func(a, b)' . a is an integer and b is a float
Traceback (most recent call last):
File "c:/a/script.py", line 9, in
func(2)
TypeError: func() takes exactly 2 arguments (1 given)
After playing around I found the answer that satisfies me the most:
import sys
import numpy
def func(integer = float("nan"), number = float("nan")):
if numpy.isnan(integer):
print "Function syntax: func(integer, number)"
sys.exit()
return integer * number
func()
>>> Function syntax: func(integer, number)
func(1)
>>> nan
func(3,2)
>>> 6
By setting my function variables to NaN I can only override them by actually giving them a value when calling the function. However, due to the if statement I can actually print the function variables by not giving any when calling it.

How can I find the names of missing parameters in Python?

Whenever a Python function is called with missing named arguments, it produces a runtime error that lists the number of missing arguments:
TypeError: getVolume() takes exactly 3 arguments (2 given)
However, this doesn't tell me which specific arguments are missing. This runtime error message would be much more informative if it actually printed the names of the missing arguments, instead of just printing the number of arguments that are missing. This is especially important when working with functions that accept a large number of arguments: it's not always easy to remember the name of every single argument that is missing.
In general, is it possible to modify Python functions so that they will print the names of the missing arguments whenever arguments are missing?
def getVolume(length, width, height):
return length*width*height;
print(getVolume(height=3, width=3));
This has changed in Python3.3 (at most), you get the missing argument names for free:
>>> def getVolume(length, width, height):
... return length*width*height;
...
>>> print(getVolume(height=3, width=3));
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: getVolume() missing 1 required positional argument: 'length'

Categories