How to get function object by name? - python

I do want to process a command with an argument specified by the user.
I thought about:
self.urlRegexFunc = "endswith"
self.urlRegex = ".mp3"
exec('b = attr[1].%s("%s")' % (self.urlRegexFunc, self.urlRegex)) # attr[1] is string
if b:
pass # Do Something
But I get:
SyntaxError: unqualified exec is not allowed in function 'start_a' it contains a nested function with free variables
What can I do?

You're looking for getattr().

Related

python: SyntaxError: invalid syntax Expected member name after "."

I'm using argparse to parse the parameters, but when I get args.global, a strange error appears, I don't know where I did it wrong
...
parser.add_argument('-u','--update', action='store_true', default=None)
parser.add_argument('-g','--global', action='store_true', default=None)
args = parser.parse_args()
...
if args.update:
print(args)
print( args.global )
print( args.update )
$ python ./anpm.py -g -u
File "./anpm.py", line 67
print( args.global )
^
SyntaxError: invalid syntax
This is the error given by vscode
$ python --version
Python 3.6.8
global is a keyword in Python (as are if, while, etc.) and you cannot use these as attribute names, which means they also don't work in a NameSpace object.
More on that here:
https://docs.python.org/3/reference/lexical_analysis.html#keywords
However, you can still access these values if you need to use these names:
my_args = vars(args)
print(my_args['global'])
This works because it doesn't use the reserved word, instead it just uses a string (containing the reserved word) to access its value.
If you only need access once, or infrequently and you don't want to keep the vars() result around, you can also just:
print(vars(args)['global'])
Use getattr:
print(getattr(args, 'global'))
This would get the attribute global.
Global Explanation
Global is a reserved keyword in python that is used to declare a variable globally inside the functional scope.
Example:
def p():
global x
x=23
p()
print(x)
//returns 23
Keywords and example
A keyword can't be used as an argument or a variable in python. you can have other examples like
yield=23
return=34
pass=34
continue=23
.....
All these make an error.
Solution
Try changing the name from global to __global or _global or something like this.

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.

python gettattr(function, __doc__) + file parsing

I need your help on gettattr(function, __doc__)
this works if you use it within the file of the definition
BUT
I want to find all functions withing a given file and then run gettattr(function, __doc__) for all the returned functions to get associated doc strings
to list all my function within the module I use :
import module
functionsList = [o for o in getmembers(module) if isfunction(o[1])]
function[0] is a string and function[1] is the memory allocation ?
if I want to use the function as a string i need to do:
for function in functionList:
exec ("docStrings = "+function[0]+".__doc__")
print docStrings
then I would have this error:
Error: NameError: file line 1: name 'anotherTestFunction' is not defined
and I tried to directly use the function
for function in functionList:
docStrings = gettattr(function[1], __doc__)
print docStrings
This time I have no error but it returns : None ...
I might be missing something ... Do you have any idea ?
Cheers
So finally... This was a stupid mistake...
I forgot the " " around _ _doc__ ...
It solves everything. But here is an other way of doing it in case. Use inspect
import module
functionsList = [o for o in getmembers(module) if isfunction(o[1])]
docString = functionsList.__doc__
this is working !

Not recognizing command line argument in Python

I am trying to add a command line argument depending on some values returned by the functions. When I am not giving that argument it says:
main.py: error: argument -opp/--operator is required
When I am giving the argument it says:
main.py: error: unrecognized arguments: -opp +
Following is the piece of EDITED code (as told in one of the answers):
parser.add_argument('-z', help='Help msg', required=True)
args, unknown = parser.parse_known_args()
value = some_functions(args.z)
if value == some_particular_value:
parser.add_argument('-opp','--operator',help='Some help msg',required=True)
args = parser.parse_args()
Please help me in adding this argument. Thanks!
There are, though, a couple of mistakes in your code. Here's the corrected version:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-z', help = 'Help msg', required = True)
args, _ = parser.parse_known_args()
# value = some_functions(args.z)
if value == some_particular_value:
parser.add_argument('-opp', '--operator', help = 'Some help msg', required = True)
# args2, _ = parser.parse_known_args()
# some_function2(args2.operator)
So, let's analyse your mistakes:
Assigning instead of comparing
That's typical newbie mistake. Within a conditional operator (if, case...) you set the value instead of checking it. The difference is in amount of the = sign.
If you assign value, the condition in the operator will be always True and test will always succeed (in most of programming languages and cases).
Check this out:
a = 1
if a = 2:
print a
This may print 2 in some languages (like C or Java; using the correct syntax). Why? You've just set it! Yet, Python is smart enough to tell you about your mistake:
File "<stdin>", line 1
if a = 2:
^
SyntaxError: invalid syntax
And compare it to this:
a = 1
if a == 2:
print a
This will not print anything. Because the if test did not pass.
Assigning value instead of calling method
You want to be using the method add_argument instead of re-defining the parser variable, right?
parser = add_argument(...)
That's something like I've described above. You should be calling a method of a parser variable, not defining its new value:
parser.add_argument(...)
Re-parsing arguments is missing?
You did not show the part of the code where you check for the operator argument. Note: you should parse your arguments again, when defined a new argument:
parser.add_argument(...)
args, _ = parser.parse_known_arguments()
Then you will get a new argument in the args variable.
Using the wrong name of argument?
Again, you are missing part of code, where you check for the operator argument' value. If you are trying to access it with
args.opp # whoops...
Then you'd just get an error saying There's no argument 'opp'!, because it has its full name and should be accessed with it:
args.operator # aaah, here it is!

Using "from" as a script argument in Python

My assignment requires that "from" be used as an argument for the command line input.
p = optparse.OptionParser()
p.add_option("--from")
p.add_option("--to")
p.add_option("--file", default="carla_coder.ics")
options, arguments = p.parse_args()
print options.from
obviously, "from" is a Python keyword... is there any way to get around this? Basically, the script should be run using
file.py --from=dd/mm/yyyy --to=dd/mm/yyyy --file=file
Use the dest attribute to specify a name:
p.add_option("--from", dest="foo")
print options.foo
Use Python's getattr function:
getattr(options, 'from')
Will behave like options.from, except that the attribute name doesn't have to follow Python's usual variable naming rules (including keyword conflicts).

Categories