Parameter naming conflict with Python - python

While implementing a third-party API (mollie), it seems they've named one of the parameters to support pagination "from" which conflicts with the built in python from.
Is there a way for me to use this properly? Am I not passing the parameters correctly? Note: they're written as **params.
The only parameters it supports are: from and limit.
from mollie.api.client import Client
c = Client().set_api_key(**KEY**)
c.subscriptions.list() # This works
c.subscriptions.list(limit=5) # This works
c.subscriptions.list(from="customer_code")
Gives:
File "main.py", line 7
c.subscriptions.list(from="customer_code")
^
SyntaxError: invalid syntax

Assuming that the Client is defined something like:
def list(**params):
# some stuff with params
print(params.get('from'))
print(params.get('limit'))
Then indeed calling list(from=5) will give a syntax error. But as the function packs all arguments to a kwargs dict and treats them as string keys, we can do the same thing on the other side - unpack a dict to the function arguments:
list(**{'from': 5, 'limit': 10})
Will indeed print:
5
10

Related

How to use Parameters in Python Luigi

How do I pass in parameters to Luigi? if I have a python file called FileFinder.py with a class named getFIles:
class getFiles(luigi.Task):
and I want to pass in a directory to this class such as:
C://Documents//fileName
and then use this parameter in my run method
def run(self):
how do I run this in command line and add the parameter for use in my code? I am accustomed to running this file in command line like this:
python FileFinder.py getFiles --local-scheduler
What do I add to my code to use a parameter, and how do I add that parameter to the command line argument?
Also, as an extension of this question, how would I use multiple arguments? or arguments of different data types such as strings or lists?
As you have already figured out, you can pass arguments to luigi via
--param-name param-value
in the command line. Inside your code, you have to declare these variables by instantiating the Parameter class or one of it's subclasses. The subclasses are used to tell luigi if the variable has a data-type that is not string. Here is an example which uses two command line arguments, one Int and one List:
import luigi
class testClass(luigi.Task):
int_var = luigi.IntParameter()
list_var = luigi.ListParameter()
def run(self):
print('Integer Param + 1 = %i' % (self.int_var + 1))
list_var = list(self.list_var)
list_var.append('new_elem')
print('List Param with added element: ' + str(list_var))
Note that ListParams actually get converted to tuples by luigi, so if you want to do list operations on them, you have to convert them back first (This is a known issue, but doesn't look like it will be fixed soon).
You can invoke the above module from the command line like this (i have saved the code as a file called "testmodule.py" and made the call from inside the same directory):
luigi --module testmodule testClass --int-var 3 --list-var '[1,2,3]' --local-scheduler
Note here that for variables containing a _, this has to be replaced by -.
The call yields (along with many status messages):
Integer Param + 1 = 4
List Param with added element: [1, 2, 3, 'new_elem']
So I think this works, in the code I added:
fileName = luigi.Parameter()
if i run this in the command line:
python FileFinder.py getFiles --local-scheduler --getFiles-fileName C://Documents//fileName
but if anyone has any advice on parameters of different types and how to use them, especially numbers and lists, please let me know.
Adding to Toterich's answer.
While passing a list of string arguments as a ListParameter():
python file_name.py --local-scheduler TaskName --arg '["a","b"]'
The string arguments must be enclosed in double-quotes and not single quotes otherwise it'll give a JSONParsing error.

Why can't I use named arguments in Python 2 for the functions from the standard library [duplicate]

I'm new at Python, and I'm trying to basically make a hash table that checks if a key points to a value in the table, and if not, initializes it to an empty array. The offending part of my code is the line:
converted_comments[submission.id] = converted_comments.get(submission.id, default=0)
I get the error:
TypeError: get() takes no keyword arguments
But in the documentation (and various pieces of example code), I can see that it does take a default argument:
https://docs.python.org/2/library/stdtypes.html#dict.get
http://www.tutorialspoint.com/python/dictionary_get.htm
Following is the syntax for get() method:
dict.get(key, default=None)
There's nothing about this on The Stack, so I assume it's a beginner mistake?
Due to the way the Python C-level APIs developed, a lot of built-in functions and methods don't actually have names for their arguments. Even if the documentation calls the argument default, the function doesn't recognize the name default as referring to the optional second argument. You have to provide the argument positionally:
>>> d = {1: 2}
>>> d.get(0, default=0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: get() takes no keyword arguments
>>> d.get(0, 0)
0
The error message says that get takes no keyword arguments but you are providing one with default=0
converted_comments[submission.id] = converted_comments.get(submission.id, 0)
Many docs and tutorials, for instance https://www.tutorialspoint.com/python/dictionary_get.htm, erroneously specify the syntax as
dict.get(key, default = None)
instead of
dict.get(key, default)

Is it possible to get a list of all the keyword arguments of a built-in function? [duplicate]

I'm trying to figure out the arguments of a method retrieved from a module.
I found an inspect module with a handy function, getargspec.
It works for a function that I define, but won't work for functions from an imported module.
import math, inspect
def foobar(a,b=11): pass
inspect.getargspec(foobar) # this works
inspect.getargspec(math.sin) # this doesn't
I'll get an error like this:
File "C:\...\Python 2.5\Lib\inspect.py", line 743, in getargspec
raise TypeError('arg is not a Python function')
TypeError: arg is not a Python function
Is inspect.getargspec designed only for local functions or am I doing something wrong?
It is impossible to get this kind of information for a function that is implemented in C instead of Python.
The reason for this is that there is no way to find out what arguments the method accepts except by parsing the (free-form) docstring since arguments are passed in a (somewhat) getarg-like way - i.e. it's impossible to find out what arguments it accepts without actually executing the function.
You can get the doc string for such functions/methods which nearly always contains the same type of information as getargspec. (I.e. param names, no. of params, optional ones, default values).
In your example
import math
math.sin.__doc__
Gives
"sin(x)
Return the sine of x (measured in radians)"
Unfortunately there are several different standards in operation. See What is the standard Python docstring format?
You could detect which of the standards is in use, and then grab the info that way. From the above link it looks like pyment could be helpful in doing just that.

Why can I bypass a "function takes exactly 1 argument (2 given)" error with assignment?

I am trying to use Twython to work with the Twitter API in python, and I am observing some behavior that seems odd to me.
If I run the following code...
from twython import Twython
from random import randint
twitter = Twython(APP_KEY, APP_SECRET, OAUTH_TOKEN, OAUTH_TOKEN_SECRET) # In the actual code, I obviously assign these, but I can't disclose them here, so the code won't work...
user_id = randint(1,250000000)
twitter_user = twitter.lookup_user(user_id)
I get this error.
Traceback (most recent call last):
File "Twitter_API_Extraction.py", line 76, in <module>
twitter_user = twitter.lookup_user(user_id) # returns a list of dictionaries with all the users requested
TypeError: lookup_user() takes exactly 1 argument (2 given)
The Twython docs indicate I only need to pass the user id or the screen name (https://twython.readthedocs.org/en/latest/api.html). Some googling suggested that this error usually mean I need to pass self as the first parameter, but I didn't quite get why.
However, if I use the following assignment instead...
twitter_user = twitter.lookup_user(user_id = randint(1,250000000))
Everything comes up roses. I can't figure out why this is, and it is a problem later in the code when I am trying to access followers using the same lookup_user function.
Any clarification on what is triggering this error and how I am bypassing it via assignment in the function call would be most appreciated!
Per the API documentation:
lookup_user(**params)
Returns fully-hydrated user objects for up to 100 users per request, as specified by comma-separated values passed to the user_id and/or screen_name parameters.
The ** syntax (documentation) means you need to provide named arguments (i.e. f(a=b)), in this case user_id and/or screen_name
In your first attempt you're trying to pass a positional argument (i.e. f(a)), which the function is not set up for.
The API states that lookup_user takes keyword arguments only. Keyword arguments take the form keyword=value, which is what you are doing with lookup_user(user_id=randint(1,...)). It means you cannot pass positional arguments, which is what you are doing with lookup_user(userid).

Python: SyntaxError: keyword can't be an expression

In a Python script I call a function from rpy2, but I get this error:
#using an R module
res = DirichletReg.ddirichlet(np.asarray(my_values),alphas,
log=False, sum.up=False)
SyntaxError: keyword can't be an expression
What exactly went wrong here?
sum.up is not a valid keyword argument name. Keyword arguments must be valid identifiers. You should look in the documentation of the library you are using how this argument really is called – maybe sum_up?
I guess many of us who came to this page have a problem with Scikit Learn, one way to solve it is to create a dictionary with parameters and pass it to the model:
params = {'C': 1e9, 'gamma': 1e-07}
cls = SVC(**params)
It's python source parser failure on sum.up=False named argument as sum.up is not valid argument name (you can't use dots -- only alphanumerics and underscores in argument names).
Using the Elastic search DSL API, you may hit the same error with
s = Search(using=client, index="my-index") \
.query("match", category.keyword="Musician")
You can solve it by doing:
s = Search(using=client, index="my-index") \
.query({"match": {"category.keyword":"Musician/Band"}})
I just got that problem when converting from % formatting to .format().
Previous code:
"SET !TIMEOUT_STEP %{USER_TIMEOUT_STEP}d" % {'USER_TIMEOUT_STEP' = 3}
Problematic syntax:
"SET !TIMEOUT_STEP {USER_TIMEOUT_STEP}".format('USER_TIMEOUT_STEP' = 3)
The problem is that format is a function that needs parameters. They cannot be strings.
That is one of worst python error messages I've ever seen.
Corrected code:
"SET !TIMEOUT_STEP {USER_TIMEOUT_STEP}".format(USER_TIMEOUT_STEP = 3)

Categories