David J.
David J.

Reputation: 1913

combining argsparse and sys.args in Python3

I'm trying to write a command line tool for Python that I can run like this..

orgtoanki 'b' 'aj.org' --delimiter="~" --fields="front,back"

Here's the script:

#!/usr/bin/env python3
import sys
import argparse

from orgtoanki.api import create_package

parser = argparse.ArgumentParser()
parser.add_argument('--fields', '-f', help="fields, separated by commas", type=str, default='front,back')
parser.add_argument('--delimiter', '-d', help="delimiter", type= str, default='*')
args = parser.parse_args()
name=sys.argv[1]
org_src=sys.argv[2]

create_package(name, org_src, args.fields, agrs.delimiter)

When I run it, I get the following error:

usage: orgtoanki [-h] [--fields FIELDS] [--delimiter DELIMITER]
orgtoanki: error: unrecognized arguments: b aj.org

Why aren't 'b' and 'ab.org' being interpreted as sys.argv[1] and sys.argv[2], respectively?

And will the default work as I expect it to, if fields and delimiter aren't supplied to the command line?

Upvotes: 0

Views: 485

Answers (2)

hpaulj
hpaulj

Reputation: 231395

The default input to parser.parse_args is sys.argv[1:].

usage: orgtoanki [-h] [--fields FIELDS] [--delimiter DELIMITER]
orgtoanki: error: unrecognized arguments: b aj.org

The error message was printed by argparse, followed by an sys exit.

The message means that it found strings in sys.argv[1:] that it wasn't programmed to recognize. You only told it about the '--fields' and '--delimiter' flags.

You could add two positional fields as suggested by others.

Or you could use

[args, extras] = parser.parse_known_args()
name, org_src = extras

extras should then be a list ['b', 'aj.org'], the unrecognized arguments, which you could assign to your 2 variables.

Parsers don't (usually) consume and modify sys.argv. So several parsers (argparse or other) can read the same sys.argv. But for that to work they have to be forgiving about strings they don't need or recognize.

Upvotes: 1

Phil Filippak
Phil Filippak

Reputation: 673

The error here is caused by argparse parser which fails to apprehend the 'b' 'aj.org' part of the command, and your code never reaches the lines with sys.argv. Try adding those arguments to the argparse and avoid using both argparse and sys.argv simultaneously:

parser = argparse.ArgumentParser()

# these two lines
parser.add_argument('name', type=str)
parser.add_argument('org_src', type=str)

parser.add_argument('--fields', '-f', help="fields, separated by commas",
                    type=str, default='front,back')
parser.add_argument('--delimiter', '-d', help="delimiter",
                    type= str, default='*')

args = parser.parse_args()

You then can access their values at args.name and args.org_src respectively.

Upvotes: 2

Related Questions