2

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?

martineau
124k29 gold badges181 silver badges319 bronze badges
asked Mar 21, 2018 at 14:11
5
  • As a side note, I would use docopt instead of argparse. Commented Mar 21, 2018 at 14:21
  • Indent your code properly please Commented Mar 21, 2018 at 14:32
  • @Romize. looks interesting. Seems simpler to use than argparse but I have a gut feeling that it won't be able to handle the very complex cases as well. Commented Mar 21, 2018 at 14:35
  • 1
    @MadPhysicist, we get these occasional recommendations to use other parsers, but never any code to show that they work better in the particular problem at hand. Commented Mar 21, 2018 at 16:59
  • 1
    When you present code that doesn't 'work', we expect you to tell us what was wrong - any error messages or results that don't match your expectations. A vague 'don't work' isn't good enough. Commented Mar 21, 2018 at 20:08

3 Answers 3

3

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

answered Mar 21, 2018 at 14:29
Sign up to request clarification or add additional context in comments.

Comments

1

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?

answered Mar 21, 2018 at 20:26

Comments

1

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)
answered Aug 22, 2019 at 9:14

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.