Python: check a function's default arguments - python

Given a function (e.g. create_instances) which takes many keyword arguments, how do I know which arguments have default values, and what exactly are the default values?
To give full context, I'm using the boto3 AWS Python API:
import boto3
ec2 = boto3.resource('ec2')
ec2.create_instances( ... )
For example, the create_instances function takes an argument MaxCount, but I want to know whether it has a default value. I looked around in the inspect module but wasn't did not find anything useful.
The documentation of create_instances is at https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ec2.html#EC2.ServiceResource.create_instances

inspect.getfullargspec(ec2.create_instance) should normally give you everything you need. Align args and defaults on the right side. For example:
def foo(a, b=3, *c, d=5):
m = a + b
return m
argspec = inspect.getfullargspec(ec2.create_instance)
{**dict(zip(argspec.args[-len(argspec.defaults):], argspec.defaults)),
**argspec.kwonlydefaults}
# => {'b': 3, 'd': 5}
As #9769953 says, if a parameter is bundled in **kwargs, it is processed by the function's code, and is thus not found in the function signature.

Related

find and call any function by function in string

It is tricky question, I need to know one thing that...
two function with different functionality and one more function called 3rd function which will decide that to use any one function. That decision will be passed as argument. Below with clarity code.
# Present in project/testing/local/funtion_one.py
def testing_function_one(par1, par2, par3):
"""do something may be add all par value"""
sum_parms = par1 + par2 + par3
return sum_params_one
# Present in project/testing/local/funtion_two.py
def testing_function_two(par1, par2, par3, par4, par5):
"""do something may be add all par value"""
sum_parms = par1 + par2 + par3
return sum_params_two
# Present in project/testing/function_testing.py
def general_function_testing(function_name, function_path, funtion_params, extra_params):
"""
function_name: would be any function testing_function_one or testing_function_two
function_path: path for where the function is located.
funtion_params: arguments for that calling function.
"""
Now I need like based on above params details, how to call the required function
using path and pass the params for that function and how to handle on passing
number of params for that perticular funtion.
I am looking like:
funt_res = function_name(funtion_params)
# After getting result do something with other params.
new_res = funt_res * extra_params
if __name__ == "__main__"
function_name = "testing_function_two"
function_path = "project/testing/local/funtion_two.py"
funtion_params = pass values to testing_function_two funtion. it
can be {"par1": 2, "par2": 2, "par3": 4, "par4": 6, "par5": 8}
extra_params = 50
res = general_function_testing(function_name, function_path,
funtion_params, extra_params)
Tried:
# This part will work only when **calling_funtion_name**
present in same file otherwise it gives error.
For me it should check all the project or specified path
f_res = globals()["calling_funtion_name"](*args, **kwargs)
print('f_ress', f_res)
anyone can try this one...
If above is not clear, let me know, i will try to explain with other examples.
Though possible, in Python, few times one will need to pass a function by its name as a string. Specially, if the wanted result is for the function to be called in its destination - the reason for that is that functions are themselves "first class objects" in Python, and can be assigned to new variable names (which will simply reference the function) and be passed as arguments to other functions.
So, if one wants to pass sin from the module math to be used as a numericd function inside some other code, instead of general_function_testing('sin', 'math', ...) one can simply write:
import math
general_function_testing(math.sin, ...)
And the function callad with this parameter can simply use whatever name it has for the parameter to call the passed function:
def general_function_testing(target_func, ...):
...
result = target_func(argument)
...
While it is possible to retrieve a function from its name and module name as strings, its much more cumbersome due to nested packages: the code retrieveing the function would have to take care of any "."s in the "function path" as you call it, make carefull use of the built-in __import__, which allows one to import a module given its name as a string, though it has a weird API, and then retrieve the function from the module using a getattr call. And all this to have the a reference to the function object itself, which could be passed as a parameter from the very first moment.
The example above doing it via strings could be:
import sys
def general_function_testing(func_name, func_path, ...):
...
__import__(func_path) # imports the module where the function lives, func_path being a string
module = sys.modules[func_path] # retrieves the module path itself
target_func = getattr(module, func_name)
result = target_func(argument)
...

Tweepy api: create_friendship() takes 1 positional argument but 2 were given

I have some code that calls a function from the Tweepy API per the docs:
api = tweepy.API(auth)
...
api.create_friendship(tweet.user.id)
Alternatively I've tried with the overload:
api.create_friendship(tweet.user.username)
Either implementation yields the error:
create_friendship() takes 1 positional argument but 2 were given
Doing some research this error can be avoided by passing in an instance of self into the function, which looks like this:
#payload('user')
def create_friendship(self, **kwargs):
""" :reference: https://developer.twitter.com/en/docs/twitter-api/v1/accounts-and-users/follow-search-get-users/api-reference/post-friendships-create
"""
return self.request(
'POST', 'friendships/create', endpoint_parameters=(
'screen_name', 'user_id', 'follow'
), **kwargs
)
However I'm just running a simple script that isn't part of a class so I don't have any scope related to self. Is there an easy way around this?
Using python 3.9
The signature and the documentation comment should have clued you in:
def create_friendship(self, **kwargs):
""" :reference: https://developer.twitter.com/en/docs/twitter-api/v1/accounts-and-users/follow-search-get-users/api-reference/post-friendships-create
"""
From this, you should be able to infer that the create_friendship method takes one (implicit) positional argument (the instance of the API class), and some number of keyword arguments. I would assume the expected keyword arguments are screen_name=, user_id=, follow=, as described on the documentation page whose link appears in the doc comment.
This means that the function should be probably invoked as
api.create_friendship(user_id=tweet.user.id)

How do I print the argument name as a string i [duplicate]

How can I find the number of arguments of a Python function? I need to know how many normal arguments it has and how many named arguments.
Example:
def someMethod(self, arg1, kwarg1=None):
pass
This method has 2 arguments and 1 named argument.
The previously accepted answer has been deprecated as of Python 3.0. Instead of using inspect.getargspec you should now opt for the Signature class which superseded it.
Creating a Signature for the function is easy via the signature function:
from inspect import signature
def someMethod(self, arg1, kwarg1=None):
pass
sig = signature(someMethod)
Now, you can either view its parameters quickly by string it:
str(sig) # returns: '(self, arg1, kwarg1=None)'
or you can also get a mapping of attribute names to parameter objects via sig.parameters.
params = sig.parameters
print(params['kwarg1']) # prints: kwarg1=20
Additionally, you can call len on sig.parameters to also see the number of arguments this function requires:
print(len(params)) # 3
Each entry in the params mapping is actually a Parameter object that has further attributes making your life easier. For example, grabbing a parameter and viewing its default value is now easily performed with:
kwarg1 = params['kwarg1']
kwarg1.default # returns: None
similarly for the rest of the objects contained in parameters.
As for Python 2.x users, while inspect.getargspec isn't deprecated, the language will soon be :-). The Signature class isn't available in the 2.x series and won't be. So you still need to work with inspect.getargspec.
As for transitioning between Python 2 and 3, if you have code that relies on the interface of getargspec in Python 2 and switching to signature in 3 is too difficult, you do have the valuable option of using inspect.getfullargspec. It offers a similar interface to getargspec (a single callable argument) in order to grab the arguments of a function while also handling some additional cases that getargspec doesn't:
from inspect import getfullargspec
def someMethod(self, arg1, kwarg1=None):
pass
args = getfullargspec(someMethod)
As with getargspec, getfullargspec returns a NamedTuple which contains the arguments.
print(args)
FullArgSpec(args=['self', 'arg1', 'kwarg1'], varargs=None, varkw=None, defaults=(None,), kwonlyargs=[], kwonlydefaults=None, annotations={})
import inspect
inspect.getargspec(someMethod)
see the inspect module
func.__code__.co_argcount gives you the number of any arguments BEFORE *args
func.__kwdefaults__ gives you a dict of the keyword arguments AFTER *args
func.__code__.co_kwonlyargcount is equal to len(func.__kwdefaults__)
func.__defaults__ gives you the values of optional arguments that appears before *args
Here is a simple illustration:
>>> def a(b, c, d, e, f=1, g=3, h=None, *i, j=2, k=3, **L):
pass
>>> a.__code__.co_argcount
7
>>> a.__defaults__
(1, 3, None)
>>> len(a.__defaults__)
3
>>>
>>>
>>> a.__kwdefaults__
{'j': 2, 'k': 3}
>>> len(a.__kwdefaults__)
2
>>> a.__code__.co_kwonlyargcount
2
someMethod.func_code.co_argcount
or, if the current function name is undetermined:
import sys
sys._getframe().func_code.co_argcount
inspect.getargspec()
Get the names and default values of a function’s arguments. A tuple of four things is returned: (args, varargs, varkw, defaults). args is a list of the argument names (it may contain nested lists). varargs and varkw are the names of the * and ** arguments or None. defaults is a tuple of default argument values or None if there are no default arguments; if this tuple has n elements, they correspond to the last n elements listed in args.
Changed in version 2.6: Returns a named tuple ArgSpec(args, varargs, keywords, defaults).
See can-you-list-the-keyword-arguments-a-python-function-receives.
Adding to the above, I've also seen that the most of the times help() function really helps
For eg, it gives all the details about the arguments it takes.
help(<method>)
gives the below
method(self, **kwargs) method of apiclient.discovery.Resource instance
Retrieves a report which is a collection of properties / statistics for a specific customer.
Args:
date: string, Represents the date in yyyy-mm-dd format for which the data is to be fetched. (required)
pageToken: string, Token to specify next page.
parameters: string, Represents the application name, parameter name pairs to fetch in csv as app_name1:param_name1, app_name2:param_name2.
Returns:
An object of the form:
{ # JSON template for a collection of usage reports.
"nextPageToken": "A String", # Token for retrieving the next page
"kind": "admin#reports#usageReports", # Th
Good news for folks who want to do this in a portable way between Python 2 and Python 3.6+: use inspect.getfullargspec() method. It works in both Python 2.x and 3.6+
As Jim Fasarakis Hilliard and others have pointed out, it used to be like this:
1. In Python 2.x: use inspect.getargspec()
2. In Python 3.x: use signature, as getargspec() and getfullargspec() were deprecated.
However, starting Python 3.6 (by popular demand?), things have changed towards better:
From the Python 3 documentation page:
inspect.getfullargspec(func)
Changed in version 3.6: This method was previously documented as deprecated in favour of signature() in Python 3.5, but that decision has been reversed in order to restore a clearly supported standard interface for single-source Python 2/3 code migrating away from the legacy getargspec() API.
You get the number of arguments by (replace "function" by the name of your function):
function.__code__.co_argcount ## 2
And the names for the arguments by:
function.__code__.co_varnames ## ('a', 'b')
As other answers suggest, getargspec works well as long as the thing being queried is actually a function. It does not work for built-in functions such as open, len, etc, and will throw an exception in such cases:
TypeError: <built-in function open> is not a Python function
The below function (inspired by this answer) demonstrates a workaround. It returns the number of args expected by f:
from inspect import isfunction, getargspec
def num_args(f):
if isfunction(f):
return len(getargspec(f).args)
else:
spec = f.__doc__.split('\n')[0]
args = spec[spec.find('(')+1:spec.find(')')]
return args.count(',')+1 if args else 0
The idea is to parse the function spec out of the __doc__ string. Obviously this relies on the format of said string so is hardly robust!
inspect.getargspec() to meet your needs
from inspect import getargspec
def func(a, b):
pass
print len(getargspec(func).args)
The accepted answer by Dimitris Fasarakis Hilliard suggests getting parameters in the string format but I think one can make a mistake when parsing this string and thus I created rather a list of the parameters directly using the inspect module
import inspect
def my_function(a,b,c):
#some code
pass
result=list(inspect.signature(my_function).parameters.keys())
print(result)
['a','b','c']
Assuming you may be dealing with class based methods or simply functions, you could do something like the following.
This will automatically subtract one input if the input is a class method (and therefore includes self).
import types
def get_arg_count(fn):
extra_method_input_count=1 if isinstance(fn, types.MethodType) else 0
return fn.__code__.co_argcount-extra_method_input_count
Then you can apply as you need to functions or methods:
def fn1(a, b, c):
return None
class cl1:
def fn2(self, a, b, c):
return None
print(get_arg_count(fn1)) #=> 3
print(get_arg_count(cl1().fn2)) #=> 3
In:
import inspect
class X:
def xyz(self, a, b, c):
return
print(len(inspect.getfullargspec(X.xyz).args))
Out:
4
Note: If xyz wasn't inside class X and had no "self" and just "a, b, c", then it would have printed 3.
For python below 3.5, you may want to replace inspect.getfullargspec by inspect.getargspec in the code above.
This is a solution to getting the number of mandatory arguments of a function (*)
Many of the solutions proposed here do not work for this purpose if some more uncommon parameter specifications are used (positional-only parameters with defaults, keyword-only parameters without defaults, etc.)
from typing import Callable, Any
import inspect
def get_mandatory_argcount(f: Callable[..., Any]) -> int:
"""Get the number of mandatory arguments of a function."""
sig = inspect.signature(f)
def parameter_is_mandatory(p: inspect.Parameter) -> bool:
return p.default is inspect.Parameter.empty and p.kind not in (
inspect.Parameter.VAR_POSITIONAL,
inspect.Parameter.VAR_KEYWORD,
)
return sum(parameter_is_mandatory(p) for p in sig.parameters.values())
# mandatory keyword-only
def f1(b=2, *args, c, d=1, **kwds): pass
print(get_mandatory_argcount(f1))
# positional only with default
def f2(a=1, /, b=3, *args, **kwargs): pass
print(get_mandatory_argcount(f2))
(*) I would have liked to put this as an answer to Programmatically determining amount of parameters a function requires - Python instead, but for some reason this question is marked as duplicate to this one despite it asking specifically about the number of required arguments whereas this question only asks about the general number of arguments.

How can I find the number of arguments of a Python function?

How can I find the number of arguments of a Python function? I need to know how many normal arguments it has and how many named arguments.
Example:
def someMethod(self, arg1, kwarg1=None):
pass
This method has 2 arguments and 1 named argument.
The previously accepted answer has been deprecated as of Python 3.0. Instead of using inspect.getargspec you should now opt for the Signature class which superseded it.
Creating a Signature for the function is easy via the signature function:
from inspect import signature
def someMethod(self, arg1, kwarg1=None):
pass
sig = signature(someMethod)
Now, you can either view its parameters quickly by string it:
str(sig) # returns: '(self, arg1, kwarg1=None)'
or you can also get a mapping of attribute names to parameter objects via sig.parameters.
params = sig.parameters
print(params['kwarg1']) # prints: kwarg1=20
Additionally, you can call len on sig.parameters to also see the number of arguments this function requires:
print(len(params)) # 3
Each entry in the params mapping is actually a Parameter object that has further attributes making your life easier. For example, grabbing a parameter and viewing its default value is now easily performed with:
kwarg1 = params['kwarg1']
kwarg1.default # returns: None
similarly for the rest of the objects contained in parameters.
As for Python 2.x users, while inspect.getargspec isn't deprecated, the language will soon be :-). The Signature class isn't available in the 2.x series and won't be. So you still need to work with inspect.getargspec.
As for transitioning between Python 2 and 3, if you have code that relies on the interface of getargspec in Python 2 and switching to signature in 3 is too difficult, you do have the valuable option of using inspect.getfullargspec. It offers a similar interface to getargspec (a single callable argument) in order to grab the arguments of a function while also handling some additional cases that getargspec doesn't:
from inspect import getfullargspec
def someMethod(self, arg1, kwarg1=None):
pass
args = getfullargspec(someMethod)
As with getargspec, getfullargspec returns a NamedTuple which contains the arguments.
print(args)
FullArgSpec(args=['self', 'arg1', 'kwarg1'], varargs=None, varkw=None, defaults=(None,), kwonlyargs=[], kwonlydefaults=None, annotations={})
import inspect
inspect.getargspec(someMethod)
see the inspect module
func.__code__.co_argcount gives you the number of any arguments BEFORE *args
func.__kwdefaults__ gives you a dict of the keyword arguments AFTER *args
func.__code__.co_kwonlyargcount is equal to len(func.__kwdefaults__)
func.__defaults__ gives you the values of optional arguments that appears before *args
Here is a simple illustration:
>>> def a(b, c, d, e, f=1, g=3, h=None, *i, j=2, k=3, **L):
pass
>>> a.__code__.co_argcount
7
>>> a.__defaults__
(1, 3, None)
>>> len(a.__defaults__)
3
>>>
>>>
>>> a.__kwdefaults__
{'j': 2, 'k': 3}
>>> len(a.__kwdefaults__)
2
>>> a.__code__.co_kwonlyargcount
2
someMethod.func_code.co_argcount
or, if the current function name is undetermined:
import sys
sys._getframe().func_code.co_argcount
inspect.getargspec()
Get the names and default values of a function’s arguments. A tuple of four things is returned: (args, varargs, varkw, defaults). args is a list of the argument names (it may contain nested lists). varargs and varkw are the names of the * and ** arguments or None. defaults is a tuple of default argument values or None if there are no default arguments; if this tuple has n elements, they correspond to the last n elements listed in args.
Changed in version 2.6: Returns a named tuple ArgSpec(args, varargs, keywords, defaults).
See can-you-list-the-keyword-arguments-a-python-function-receives.
Adding to the above, I've also seen that the most of the times help() function really helps
For eg, it gives all the details about the arguments it takes.
help(<method>)
gives the below
method(self, **kwargs) method of apiclient.discovery.Resource instance
Retrieves a report which is a collection of properties / statistics for a specific customer.
Args:
date: string, Represents the date in yyyy-mm-dd format for which the data is to be fetched. (required)
pageToken: string, Token to specify next page.
parameters: string, Represents the application name, parameter name pairs to fetch in csv as app_name1:param_name1, app_name2:param_name2.
Returns:
An object of the form:
{ # JSON template for a collection of usage reports.
"nextPageToken": "A String", # Token for retrieving the next page
"kind": "admin#reports#usageReports", # Th
Good news for folks who want to do this in a portable way between Python 2 and Python 3.6+: use inspect.getfullargspec() method. It works in both Python 2.x and 3.6+
As Jim Fasarakis Hilliard and others have pointed out, it used to be like this:
1. In Python 2.x: use inspect.getargspec()
2. In Python 3.x: use signature, as getargspec() and getfullargspec() were deprecated.
However, starting Python 3.6 (by popular demand?), things have changed towards better:
From the Python 3 documentation page:
inspect.getfullargspec(func)
Changed in version 3.6: This method was previously documented as deprecated in favour of signature() in Python 3.5, but that decision has been reversed in order to restore a clearly supported standard interface for single-source Python 2/3 code migrating away from the legacy getargspec() API.
You get the number of arguments by (replace "function" by the name of your function):
function.__code__.co_argcount ## 2
And the names for the arguments by:
function.__code__.co_varnames ## ('a', 'b')
As other answers suggest, getargspec works well as long as the thing being queried is actually a function. It does not work for built-in functions such as open, len, etc, and will throw an exception in such cases:
TypeError: <built-in function open> is not a Python function
The below function (inspired by this answer) demonstrates a workaround. It returns the number of args expected by f:
from inspect import isfunction, getargspec
def num_args(f):
if isfunction(f):
return len(getargspec(f).args)
else:
spec = f.__doc__.split('\n')[0]
args = spec[spec.find('(')+1:spec.find(')')]
return args.count(',')+1 if args else 0
The idea is to parse the function spec out of the __doc__ string. Obviously this relies on the format of said string so is hardly robust!
inspect.getargspec() to meet your needs
from inspect import getargspec
def func(a, b):
pass
print len(getargspec(func).args)
The accepted answer by Dimitris Fasarakis Hilliard suggests getting parameters in the string format but I think one can make a mistake when parsing this string and thus I created rather a list of the parameters directly using the inspect module
import inspect
def my_function(a,b,c):
#some code
pass
result=list(inspect.signature(my_function).parameters.keys())
print(result)
['a','b','c']
Assuming you may be dealing with class based methods or simply functions, you could do something like the following.
This will automatically subtract one input if the input is a class method (and therefore includes self).
import types
def get_arg_count(fn):
extra_method_input_count=1 if isinstance(fn, types.MethodType) else 0
return fn.__code__.co_argcount-extra_method_input_count
Then you can apply as you need to functions or methods:
def fn1(a, b, c):
return None
class cl1:
def fn2(self, a, b, c):
return None
print(get_arg_count(fn1)) #=> 3
print(get_arg_count(cl1().fn2)) #=> 3
In:
import inspect
class X:
def xyz(self, a, b, c):
return
print(len(inspect.getfullargspec(X.xyz).args))
Out:
4
Note: If xyz wasn't inside class X and had no "self" and just "a, b, c", then it would have printed 3.
For python below 3.5, you may want to replace inspect.getfullargspec by inspect.getargspec in the code above.
This is a solution to getting the number of mandatory arguments of a function (*)
Many of the solutions proposed here do not work for this purpose if some more uncommon parameter specifications are used (positional-only parameters with defaults, keyword-only parameters without defaults, etc.)
from typing import Callable, Any
import inspect
def get_mandatory_argcount(f: Callable[..., Any]) -> int:
"""Get the number of mandatory arguments of a function."""
sig = inspect.signature(f)
def parameter_is_mandatory(p: inspect.Parameter) -> bool:
return p.default is inspect.Parameter.empty and p.kind not in (
inspect.Parameter.VAR_POSITIONAL,
inspect.Parameter.VAR_KEYWORD,
)
return sum(parameter_is_mandatory(p) for p in sig.parameters.values())
# mandatory keyword-only
def f1(b=2, *args, c, d=1, **kwds): pass
print(get_mandatory_argcount(f1))
# positional only with default
def f2(a=1, /, b=3, *args, **kwargs): pass
print(get_mandatory_argcount(f2))
(*) I would have liked to put this as an answer to Programmatically determining amount of parameters a function requires - Python instead, but for some reason this question is marked as duplicate to this one despite it asking specifically about the number of required arguments whereas this question only asks about the general number of arguments.

Python newbie: What does this code do?

This is a snippet from Google AppEngine tutorial.
application = webapp.WSGIApplication([('/', MainPage)], debug=True)
I'm not quite sure what debug=True does inside the constructor call.
Does it create a local variable with name debug, assign True to it, and pass it to constructor, or is this a way to set a class instance member variable's value in constructor?
Python functions accept keyword arguments. If you define a function like so:
def my_func(a, b='abc', c='def'):
print a, b, c
You can call it like this:
my_func('hello', c='world')
And the result will be:
hello abc world
You can also support dynamic keyword arguments, using special syntax:
def my_other_func(a, *b, **c):
print a, b, c
*b means that the b variable will take all non-named arguments after a, as a tuple object.
**c means that the c variable will take all named arguments, as a dict object.
If you call the function like this:
my_other_func('hello', 'world', 'what a', state='fine', what='day')
You will get:
hello ('world', 'what a') {'state': 'fine', 'what': 'day'}
Neither -- rather, webapp.WSGIApplication takes an optional argument named debug, and this code is passing the value True for that parameter.
The reference page for WSGIApplication is here and it clearly shows the optional debug argument and the fact that it defaults to False unless explicitly passed in.
As the page further makes clear, passing debug as True means that helpful debugging information is shown to the browser if and when an exception occurs while handling the request.
How exactly that effect is obtained (in particular, whether it implies the existence of an attribute on the instance of WSGIApplication, or how that hypothetical attribute might be named) is an internal, undocumented implementation detail, which we're not supposed to worry about (of course, you can study the sources of WSGIApplication in the SDK if you do worry, or just want to learn more about one possible implementation of these specs!-).
It's using named arguments. See Using Optional and Named Arguments.

Categories