Domanda

I am writing a program that takes a list of urls as a parameter. Optionally, I would like to also be able to include a file containing a list of additional urls. Thus the program help would look like a combination of the below:

usage: [-h] url [url ...]

or

usage: [-h] --input-file file [ url [url ...]]

I am currently programming it as:

usage: [-h] [--input-file file] [url [url ...]]

where both usage of --input-file and specifying at least one url is optional. I am then checking myself if either the input-file or list of urls is specified.

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-i','--input-file', help="File of urls to be read")
parser.add_argument('urls',nargs='*')
args = parser.parse_args()
if not args.input_list and not args.urls:
    parser.error('must have either an input-file or a url') 

Is there a way in argparse where I can force the user to specify a url if no input-file is given, but make it optional if it is?

È stato utile?

Soluzione

If you specify a fromfile-prefix-chars (such as @), the user could specify a file to read these urls from. The lines of this file are read and added to the sys.argv just as though they had been typed in the command line.

http://docs.python.org/dev/library/argparse.html#fromfile-prefix-chars

parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
parser.add_argument('urls',nargs='+')  # require 1 or more url
args = parser.parse_args()

these all work (where urls.txt has one url string per line)

parser.parse_args('four.txt'.split())
parser.parse_args('@urls.txt four.txt'.split())
parser.parse_args('@urls.txt'.split())

while no file or url gives an error

parser.parse_args(''.split())

The default help does not say anything about allowing that @url.txt file name, but you could add that in a custom description string.

PS - Your post-argparse test is simpler than anything you could specify in argparse. A required mutually-exclusive-group involving the -i argument and the positional might work, but it doesn't do much more than your test. I wrote 'might' because I'd have to double whether a '*' positional works in such a group. But this is one of the first cases I've seen where that fromfile_prefix_chars option would be genuinely useful.

Altri suggerimenti

ArgumentParser.add_mutually_exclusive_group() should help you accomplish your goal. Have a look at the example at https://docs.python.org/2/library/argparse.html#mutual-exclusion or the code below:

~#: cat urls.py
import argparse

parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('-infile', dest='file', help='File of URLs to be read')
group.add_argument('-urls', dest='urls', nargs='+', help='One or more URLs')

args = parser.parse_args()

~#: python urls.py
usage: urls.py [-h] (-infile FILE | -urls URLS [URLS ...])
urls.py: error: one of the arguments -infile -urls is required
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top