Reputation: 107
I am trying to use argparse to create my script with parameters but I am not being able to.
The name of my script is pipeline
and it has some options arguments like -b, -c, -i and -r.
If you call the script ./pipeline -b
should give an error asking for a git repository path but I am not being able to do this.
from git import Repo
import os
import sys
import subprocess
import argparse
class Ci:
def build(self,args):
cloned_repo = Repo.clone_from(args)
print("clonning repository " + args)
cloned_repo
dir = git.split('/')(-1)
if os.path.isdir(dir):
print("repository cloned successfully")
else:
print("error to clone repository")
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-b','-build',action='store_true', help='execute mvn clean install')
parser.add_argument('-c','-compress',action='store_true',help='zip a directory recursively')
parser.add_argument('-i','-integration',action='store_true',help='execute mvn verify')
parser.add_argument('-r','-release',action='store_true',help='execute build,integration and compress respectively')
args = parser.parse_args()
if args.b:
a = Ci()
a.build()
if len(sys.argv) < 2:
parser.print_help()
sys.exit(1)
I can't make this sub-parameter work and I can't find a way to pass this parameter to my build
function.
e.g:
./pipeline -b
Output: error missins git path
./pipeline -b https://git/repo
Output: clonning repo
and the string "https://git/repo"
has to be passed as the argument to my build
function:
How can I make it work?
Upvotes: 2
Views: 2172
Reputation: 433
I agree with @hpaulj (why isn't an accepted answer?). I guess you found your problem, i.e., store_true does not take argument, then follow hpaulj indications.
In addition, I opened the question because of its title, I was expecting something different such as the following. I wanted to find a way to pass the argparse arguments to a function and possibly modify them with the function arguments. Here is the solution I wrote in case others come looking for this. It may need to be adjusted to account for positional arguments, I also highlight the possible use of vars(args) to get a dictionary from the argparse arguments to compare dict-to-dict with the args_dict:
def get_options(args_dict: dict):
""" get options from command-line,
update with function args_dict if needed """
args = get_cmd() # this is the function taking cmd-line arguments
for key, val in args_dict.items():
if not hasattr(args, key):
raise AttributeError('unrecognized option: ', key)
else:
setattr(args, key, val)
return(args)
Upvotes: 1
Reputation: 231738
Reducing your code to:
import argparse
class Ci:
def build(self,args):
print("clonning repository " + args)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-b','-build',action='store_true', help='execute mvn clean install')
parser.add_argument('-c','-compress',action='store_true',help='zip a directory recursively')
parser.add_argument('-i','-integration',action='store_true',help='execute mvn verify')
parser.add_argument('-r','-release',action='store_true',help='execute build,integration and compress respectively')
args = parser.parse_args()
print(args)
if args.b:
a = Ci()
a.build()
I get:
1313:~/mypy$ python3 stack49408644.py -b
Namespace(b=True, c=False, i=False, r=False)
Traceback (most recent call last):
File "stack49408644.py", line 22, in <module>
a.build()
TypeError: build() missing 1 required positional argument: 'args'
The parser runs fine, seeing args.b
to True
. But the call to build
is wrong. It does not match the method's definition.
Providing a 'directory' doesn't help either, because -b
is True/False
1313:~/mypy$ python3 stack49408644.py -b foo
usage: stack49408644.py [-h] [-b] [-c] [-i] [-r]
stack49408644.py: error: unrecognized arguments: foo
You need to either change -b
to take an value, or add another argument that takes a value.
@AntiMatterDynamite showed how to change -b
. Instead let's add:
parser.add_argument('adir', help='a directory for build')
and change the build
call
a.build(args.adir)
Now the value is passed on to the method:
1322:~/mypy$ python3 stack49408644.py -b
usage: stack49408644.py [-h] [-b] [-c] [-i] [-r] adir
stack49408644.py: error: the following arguments are required: adir
1322:~/mypy$ python3 stack49408644.py -b foo
Namespace(adir='foo', b=True, c=False, i=False, r=False)
clonning repository foo
Instead redefining -b
:
parser.add_argument('-b','-build', help='execute mvn clean install')
if args.b is not None:
a = Ci()
a.build(args.b)
test runs:
1322:~/mypy$ python3 stack49408644.py -b
usage: stack49408644.py [-h] [-b B] [-c] [-i] [-r]
stack49408644.py: error: argument -b/-build: expected one argument
1324:~/mypy$ python3 stack49408644.py -b foo
Namespace(b='foo', c=False, i=False, r=False)
clonning repository foo
So your parser needs to accept a value. And you need to pass that value on to your code. You seem to have read enough of the argparse
docs to get things like print_help
and store_true
, but missed the simpler use of store
(default) or positional. Were you trying to do something more sophisticated?
Upvotes: 1
Reputation: 1512
first a note about convention: usually the longer option name is preceded by two hyphens like this '--build'
second, 'store_true'
is the action you perform with '-b'
, which means argparse doesnt expect an argument after it, it just sets the args.build
variable to True
(and if the argument wasn't there it would set it to False
)
try removing the action='store_true'
and then it will default to storing the next value it finds in the argument list into args.build
Upvotes: 3