3

In the script I'm writing, I am using argparse for the main arguments (for --help, --todo, etc.) but trying to use sys.argv to get the name of a file given as the third argument for --add. I was using this:

def parseargs():
    parser = argparse.ArgumentParser(add_help=False)

    parser.add_argument("--help", help="Print argument usage", action="store_true")
    parser.add_argument("--memo", help="Read memo file", action="store_true")
    parser.add_argument("--todo", help="Read TODO file", action="store_true")
    parser.add_argument("--trackedfiles", help="Read tracked files list", action="store_true")

    parser.add_argument("--add", help="Add a file to trackedfiles", action="store_true")
    parser.add_argument("--edit", help="Edit file in .wpm_data with editor", action="store_true")
    parser.add_argument("--newdir", help="Create a new directory to initialize user-data", action="store_true")

    parser.add_argument("file")

    p_args = parser.parse_args()

    if p_args.help:
        printargs()
        sys.exit()

    if p_args.memo:
        print_memo()
        sys.exit()

    if p_args.todo:
        print_todo()
        sys.exit()

    if p_args.trackedfiles:
        print_trackedfiles()
        sys.exit()

    if p_args.add: # this is were I'm stumpped
        if p_args.file == sys.argv[2]:
            givenfile = p_args.file
        else:
            pass

        print("[!]\t", givenfile, "to be added to trackedfiles")

        sys.exit()

Which works like this:

./main.py --add textfile.txt
[!]  textfile.txt to be added to trackedfiles

But when a different argument would be used like --help, a third argument needs to be used for givenfile

./main.py --help            
usage: main.py [--help] [--memo] [--todo] [--trackedfiles] [--add] [--edit]
               [--newdir]
               file
    main.py: error: the following arguments are required: file

How can I separate using argparse and sys.argv, with sys.argv not constantly needing to be used so it can only be called when a function that needs it is run?

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
tolbiac
  • 67
  • 1
  • 6
  • your `if` statement returns true on `p_args.add` because you do `store_true`, even if you dont use `--add` while running the program – letsc Apr 29 '15 at 22:40

2 Answers2

2

You are doing it wrong. Here is some example that will help you understand how to use argparse. The flags aren't booleans, they can have values.

import argparse
parser = argparse.ArgumentParser(description="This program does cool things.")

parser.add_argument("--add", help="Add a file to trackedfiles")
parser.add_argument("--dell", help="Delete file")
parser.add_argument("--copy", help="Copy file")
p_args = parser.parse_args()

print "Add-->.", p_args.add
print "Dell->.", p_args.dell  #del is reserved word so we use dell
print "Copy->.", p_args.copy

And here is the usage.

$ python p.py --dell file1.txt --copy file2.txt --add file3.txt
Add-->. file3.txt
Dell->. file1.txt
Copy->. file2.txt

I hope this helps.

Hristo Ivanov
  • 679
  • 8
  • 25
0

I'm guessing a bit as to what you want to do, but here's my suggestion:

def parseargs():
    parser = argparse.ArgumentParser()
    # use the normal help, unless your `printargs` is much better
    parser.add_argument("--memo", help="Read memo file", action="store_true")
    parser.add_argument("--todo", help="Read TODO file", action="store_true")
    parser.add_argument("--trackedfiles", help="Read tracked files list", action="store_true")

    parser.add_argument("--add", help="Add a file to trackedfiles")  # takes a filename argument
    parser.add_argument("--edit", help="Edit file in .wpm_data with editor")  # takes a filename argument
    parser.add_argument("--newdir", help="Create a new directory to initialize user-data")  # takes a directory name argument

    p_args = parser.parse_args()

    if p_args.memo:
        print_memo()
    eliif p_args.todo:
        print_todo()
    elif p_args.trackedfiles:
        print_trackedfiles()
    elif p_args.add:  # could be 'if is not None:'
        add_file(p_args.add)
    elif p_args.edit:
        ....

So the big change is making the 'filename' an argument to the '--add' or '--edit' flag, not a positional. If it is a required positional argument, you'll get an error message if you omit it with arguments like --memo.

Alternatively file could be a nargs='?' positional.

You could also set this up as a subparsers case, where memo,todo,trackfiles,add,etc are all 'commands'. Some of these subparsers will take a 'file' argument, others not. I expect someone else will elaborate on that.

How do I check for a particular subparser? has a good subparsers answer.


A non-subparsers alternative:

parser = argparse.ArgumentParser()
parser.add_argument('cmd', 
     choices=['memo','todo','trackfiles','add','edit','newdir'],
     help='action to take')
parser.add_argument('name',nargs='?',help='file or dir name')
args = parser.parse_args()
if args.cmd in ['memo']:
   print_memo()
elif args.cmd in ['todo']:
   ...
elif args.cmd in ['add']:
   add_file(args.name)
elif ...

This should accept commands like prog.py memo, prog.py add myfile. add_file(afilename) should do something intelligent if its argument is None or a bad filename.

If you want to accept more than one of these 'commands' per call, then we will need to make some changes.

Community
  • 1
  • 1
hpaulj
  • 221,503
  • 14
  • 230
  • 353