I'm trying to use click to pass command-line arguments to a function but having difficulty. I'm trying to pass two command-line arguments with this:
python script.py --first-a hi --second-a there
Here's my attempt:
import click
#click.command()
#click.option("--first-a")
#click.option("--second-a")
def main(first_a, second_a):
print first_a, second_a
if __name__ == "__main__":
main(first_a, first_a)
This fails with:
NameError: name 'first_a' is not defined
I thought this had to do with dashes vs. underscores but removing the dashes and underscores (just using firsta and seconda) also fails with the same issue.
What am I doing incorrectly?
You need to call main() either without any arguments, or with a list of parameters as would normally be found in sys.argv.
Code:
if __name__ == "__main__":
main()
Test Code:
import click
#click.command()
#click.option("--first-a")
#click.option("--second-a")
def main(first_a, second_a):
print(first_a, second_a)
if __name__ == "__main__":
# test code
import sys
sys.argv[1:] = ['--first-a', 'hi', '--second-a', 'there']
# actual call to click command
main()
Results:
hi there
Related
I am using the click library and I have a function "agent_diff" that takes in three arguments...and I would like to take in arguments from the CLI and pass that into my function. But I am not entirely sure how to pass those values into "agent_diff". Here is the current code that I have:
#!/usr/bin/env python
import os
from sys import path
path.append(os.getcwd())
from src.main.scripts.bitbucket import *
import click
#click.command()
#click.argument('arg')
#click.option('--repository')
#click.option('tag1')
#click.option('tag2')
def main(arg):
print(os.path.expanduser("~"))
if arg.upper() == 'ORB-LIST':
print('Printing List of Orbs:')
orb_list()
if arg.upper() == 'AGENT-LIST':
print('Printing List of Agents:')
agent_list()
if arg.upper() == 'AGENT-DIFF':
agent_diff()
if __name__ == '__main__':
main()
Any insight would be wonderful! Thank you.
The click arguments and options must correspond to the arguments of the function. See the example below.
#click.command()
#click.argument('arg')
#click.option('--repository')
#click.option('tag1')
#click.option('tag2')
def main(arg, repository, tag1, tag2):
# do stuff...
pass
The order of the arguments does not matter.
I have the following file: up.py
in this file:
def main(a_param, b_param, c_param):
// Code
if __name__ == '__main__':
exit(main())
I want to run this python file via the CMD, so I write this line:
python up.py False True False
But I get the next error:
TypeError: main() takes exactly 3 arguments (0 given)
This has nothing to do with CMD. Your main function expects three arguments, but you aren't passing any; you call it directly from your if __name__ == '__main__' block with just main().
Either get the arguments (eg from sys.argv) within that block and pass them to main, or remove the arguments from the function signature and get them within main.
You are trying to call your main function without arguments event though it requires 3 (a_param, b_param and c_param).
The command line parameters are stored in sys.argv. To call the main function with the first 3 command line parameters, you could this:
import sys
if __name__ == '__main__':
main(*sys.argv[1:4])
To clarify, * unpacks the argument list so main(*sys.argv[1:4]) is equivalent to main(sys.argv[1], sys.argv[2], sys.argv[3])
This code works for me
def main(a_param, b_param, c_param):
# Code
if __name__ == '__main__':
exit(main())
then:
$ python up.py False True False
If I am using argparse and an if __name__ == '__main__' test in a script that I would also like to use as a module, should I import argparse under that test and then initialize it? None of the style guides I have found mention using argparse in scripts and many examples of argparse scripting do not use the 'if name' test or use it differently. Here is what I have been going with so far:
#! /usr/bin/env python
def main(name):
print('Hello, %s!' % name)
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser(description = 'Say hello')
parser.add_argument('name', help='your name, enter it')
args = parser.parse_args()
main(args.name)
Should I import argparse with my other modules at the top and configure it in the body of the script instead?
I would put the import at the top, but leave the code that uses it inside the if __name__ block:
import argparse
# other code. . .
def main(name):
print('Hello, %s!' % name)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description = 'Say hello')
parser.add_argument('name', help='your name, enter it')
args = parser.parse_args()
main(args.name)
Putting the imports at the top clarifies what modules your module uses. Importing argpase even when you don't use it will have negligible performance impact.
It's fine to put the import argparse within the if __name__ == '__main__' block if argparse is only referred to within that block. Obviously the code within that block won't run if your module is imported by another module, so that module would have to provide its own argument for main (possibly using its own instance of ArgumentParser).
I want to do the following:
I have a class which should provide several functions, which need different inputs. And I would like to use these functions from within other scripts, or solely from commandline.
e.g. I have the class "test". It has a function "quicktest" (which basically justs prints something). (From commandline) I want to be able to
$ python test.py quicktest "foo" "bar"
Whereas quicktest is the name of the function, and "foo" and "bar" are the variables.
Also (from within another script) I want to
from test import test
# this
t = test()
t.quicktest(["foo1", "bar1"])
# or this
test().quicktest(["foo2", "bar2"])
I just can't bring that to work. I managed to write a class for the first request and one for the second, but not for both of them. The problem is that I sometimes have to call the functions via (self), sometimes not, and also I have to provide the given parameters at any time, which is also kinda complicated.
So, does anybody have an idea for that?
This is what I already have:
Works only from commandline:
class test:
def quicktest(params):
pprint(params)
if (__name__ == '__main__'):
if (sys.argv[1] == "quicktest"):
quicktest(sys.argv)
else:
print "Wrong call."
Works only from within other scripts:
class test:
_params = sys.argv
def quicktest(self, params):
pprint(params)
pprint(self._params)
if (__name__ == '__main__'):
if (sys.argv[1] == "quicktest"):
quicktest()
else:
print "Wrong call"
try the following (note that the different indentation, the if __name__ part is not part of class test anymore):
class test:
def quicktest(params):
pprint(params)
if __name__ == '__main__':
if sys.argv[1] == "quicktest":
testObj = test()
testObj.quicktest(sys.argv)
else:
print "Wrong call."
from other scripts:
from test import test
testObj = test()
testObj.quicktest(...)
The if __name__ == '__main__': block needs to be at the top level:
class Test(object): # Python class names are capitalized and should inherit from object
def __init__(self, *args):
# parse args here so you can import and call with options too
self.args = args
def quicktest(self):
return 'ret_value'
if __name__ == '__main__':
test = Test(sys.argv[1:])
You can parse the command line with the help of argparse to parse the value from the command line.
Your class which has the method and associate methods to arguments.
For example let's say I have a file called myscript.py
This file contains the following code.
foo(var):
return var
How would I call the function foo with argument var on command line.
I know that I can go to the directory myscript.py is placed in and type.
>>> python myscript.py
Which will run myscript.py. The only problem is myscript.py doesn't automatically call foo when it is run.
I have tried using
if __name__ == "__main__":
foo( )
Which does not work for me. For some reason when I do that nothing happens. I get no error message and nothing is called.
You don't get any output because you don't generate any. Try calling print:
def foo(var):
print(var)
if __name__ == '__main__':
foo('Hello, world')
You have to use the sys module to pass arguments from the command line.
You can do this:
import sys
def foo(var):
return var
if __name__ == '__main__':
# arguments check
if len(sys.argv) != 2:
print "USAGE: %s <value>" % sys.argv[0]
sys.exit(1)
# get the agument so as to use it to the function call
arg = sys.argv[1]
# call the function using this argument
val = foo(arg)
# print the returned value
print val
Then you can run your python script by this command:
python myscript.py 3
giving as argument e.g. the number 3