I want to give my program a path to a file but it doesnot like it if there is a / included. How can I convince python that my path is only 1 argument
#!/usr/bin/env python
import argparse
parser = argparse.ArgumentParser(description='Change the option prefix characters',prefix_chars='-+/',)
parser.add_argument('-f', action='store', dest='PathtoFile',help='PathtoFile')
print parser.parse_args()
it works without /
argsparse.py -f banana -> Namespace(PathtoFile='banana')
Any of those result in expect one argument
argsparse.py -f /home/user/banana
argsparse.py -f '/home/user/banana'
argsparse.py -f '//home//user//banana'
argsparse.py -f "/home/user/banana"
argsparse.py -f "//home//user//banana"
->
usage: argsparse.py [-h] [-f PATHTOFILE]
argsparse.py: error: argument -f: expected one argument
UPDATE: Thanks match I forgot I added / as a prefix
Change
parser = argparse.ArgumentParser(description='Change the option prefix characters',prefix_chars='-+/',)
to
parser = argparse.ArgumentParser(description='Change the option prefix characters',prefix_chars='-+',)
The problem is that you're using prefix_chars='-+/' - this tells argparse that those characters are what mark out the command flags.
So your code is seeing / as equivalent to - and reading it as if you'd typed:
argsparse.py -f -home/user/banana
This means that -f has not been given an argument. Remove the prefix_chars and it should work properly.
Is there any way to do required argument for crystal program?
For example
./myprog ~/Music -r
Instead of
./myprog -d ~/Music -r
So my program wont run if there's no [directory] argument. Right now using "option_parser" and can only do -arguments.
There is no way to create required arguments using option_parser, but you can parse arguments and throw an error or exit if there is no argument passed you expect:
require "option_parser"
directory = nil
parser = OptionParser.new
parser.on("-d DIR", "Directory [required]") do |d|
directory = d
end
parser.parse ARGV
if directory.nil?
# directory argument was not set
# print help and exit
puts parser
exit 1
else
# ...
end
I'd like to have a program that takes a --action= flag, where the valid choices are dump and upload, with upload being the default. If (and only if) dump is selected, I'd like there to also be a --dump-format= option. Is there a way to express this using argparse, or do I need to just accept all the arguments and do the logic myself.
The argparse module offers a way to do this without implementing your own
requiredness checks. The example below uses "subparsers" or "sub commands".
I've implemented a subparser for "dump" and one for "format".
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('file', help='The file you want to act on.')
subparsers = parser.add_subparsers(dest='subcommand')
subparsers.required = True # required since 3.7
# subparser for dump
parser_dump = subparsers.add_parser('dump')
# add a required argument
parser_dump.add_argument(
'format',
choices=['csv', 'json'],
help='Dump the file in this format.')
# subparser for upload
parser_upload = subparsers.add_parser('upload')
# add a required argument
parser_upload.add_argument(
'server',
choices=['amazon', 'imgur'],
help='Upload the file to this service.')
args = parser.parse_args()
print args
if args.subcommand == 'dump':
print 'I will now dump "%s" in the %s format' % (args.file, args.format)
if args.subcommand == 'upload':
print 'I will now upload "%s" to %s' % (args.file, args.server)
That looks like this on the command line:
$ python ap.py
usage: ap.py [-h] file {upload,dump} ...
ap.py: error: too few arguments
$ python ap.py tmp.txt
usage: ap.py [-h] file {upload,dump} ...
ap.py: error: too few arguments
Upload:
$ python ap.py tmp.txt upload
usage: ap.py file upload [-h] {amazon,imgur}
ap.py file upload: error: too few arguments
$ python ap.py tmp.txt upload amazo
usage: ap.py file upload [-h] {amazon,imgur}
ap.py file upload: error: argument server: invalid choice: 'amazo' (choose from 'amazon', 'imgur')
$ python ap.py tmp.txt upload amazon
Namespace(file='tmp.txt', server='amazon', subcommand='upload')
I will now upload "tmp.txt" to amazon
$ python ap.py tmp.txt upload imgur
Namespace(file='tmp.txt', server='imgur', subcommand='upload')
I will now upload "tmp.txt" to imgur
Dump:
$ python ap.py tmp.txt dump
usage: ap.py file dump [-h] {csv,json}
ap.py file dump: error: too few arguments
$ python ap.py tmp.txt dump csv
Namespace(file='tmp.txt', format='csv', subcommand='dump')
I will now dump "tmp.txt" in the csv format
$ python ap.py tmp.txt dump json
Namespace(file='tmp.txt', format='json', subcommand='dump')
I will now dump "tmp.txt" in the json format
More info: ArgumentParser.add_subparsers()
Another way to approach the problem is by using subcommands (a'la git) with "action" as the first argument:
script dump --dump-format="foo"
script upload
You could use parser.error:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--action', choices=['upload', 'dump'], default='dump')
parser.add_argument('--dump-format')
args = parser.parse_args()
if args.action != 'dump' and args.dump_format:
parser.error('--dump-format can only be set when --action=dump.')
It depends what you consider "doing all the logic yourself". You can still use argparse and add the dump option as follows with minimal effort without resorting to sub-commands:
from argparse import ArgumentParser
from sys import argv
parser = ArgumentParser()
action_choices = ['upload', 'dump']
parser.add_argument('--action', choices=action_choices, default=action_choices[1])
parser.add_argument('--dump-format', required=(action_choices[1] in argv))
This way argparse won't care about the dump format if the dump action wasn't selected
Try this.
Suppose you have a tool that lists, adds and deletes records in a table with the following structure:
id
sitekey
response
status
1
123456
valid
a
2
234567
invalid
3
345678
invalid
c
4
456789
valid
d
And you want to have the following operations and arguments:
list
from: optional
to: optional
short-response: optional
add
sitekey: required
response: required
status: optional
remove
id: required
Then, you can have a code similar to the following:
import argparse
import sys
operation_choices = ['list', 'add', 'remove']
parser = argparse.ArgumentParser()
parser.add_argument("--operation",
choices = operation_choices,
default = operation_choices[0],
help = "Your help!",
required = True)
# list operation subarguments
if True in list(map(lambda x: operation_choices[0] in x, sys.argv)):
parser.add_argument("--from",
type = int,
default = 1,
help = "Your help!",
required = False)
parser.add_argument("--to",
type = int,
help = "Your help!",
required = False)
parser.add_argument("--short-response",
type = bool,
default = True,
help = "Your help!",
required = False)
# add operation subarguments
if True in list(map(lambda x: operation_choices[1] in x, sys.argv)):
parser.add_argument("--sitekey",
type = str,
help = "Your help!",
required = True)
parser.add_argument("--response",
type = str,
help = "Your help!",
required = True)
parser.add_argument("--status",
type = str,
help = "Your help!",
required = False)
# remove operation subarguments
if True in list(map(lambda x: operation_choices[2] in x, sys.argv)):
parser.add_argument("--id",
type = int,
help = "Your help!",
required = True)
args = parser.parse_args()
# Your operations...
So when you run:
$ python tool.py --operation=list
This run, no required arguments
$ python tool.py --operation=add
usage: tool.py [-h] --operation {list,add,remove} --sitekey SITEKEY --response RESPONSE [--status STATUS]
tool.py: error: the following arguments are required: --sitekey, --response
$ python tool.py --operation=remove
usage: tool.py [-h] --operation {list,add,remove} --id ID
tool.py: error: the following arguments are required: --id
$ python tool.py --help
usage: tool.py [-h] --operation {list,add,remove}
options:
-h, --help show this help message and exit
--operation {list,add,remove}
Your help!
$ python tool.py --operation=list --help
usage: tool.py [-h] --operation {list,add,remove} [--from FROM] [--to TO] [--short-response SHORT_RESPONSE]
options:
-h, --help show this help message and exit
--operation {list,add,remove}
Your help!
--from FROM Your help!
--to TO Your help!
--short-response SHORT_RESPONSE
Your help!
$ python tool.py --operation=add --help
usage: tool.py [-h] --operation {list,add,remove} --sitekey SITEKEY --response RESPONSE [--status STATUS]
options:
-h, --help show this help message and exit
--operation {list,add,remove}
Your help!
--sitekey SITEKEY Your help!
--response RESPONSE Your help!
--status STATUS Your help!
$ python tool.py --operation=remove --help
usage: tool.py [-h] --operation {list,add,remove} --id ID
options:
-h, --help show this help message and exit
--operation {list,add,remove}
Your help!
--id ID Your help!
I am trying to set up two different environments (development and test) on a single machine where I am using fetchmail/procmail. How would I specify a procmail script other than .procmailrc?
You can optionally specify an alternate rcfile on the command line (or even multiple files).
$ procmail -h 2>&1 | head -n 4
Usage: procmail [-vptoY] [-f fromwhom] [parameter=value | rcfile] ...
Or: procmail [-toY] [-f fromwhom] [-a argument] ... -d recipient ...
Or: procmail [-ptY] [-f fromwhom] -m [parameter=value] ... rcfile [arg] ...
Or: procmail [-toY] [-a argument] ... -z
See the ARGUMENTS section of the manual page for precise details.
With the -m option, the rcfile argument is mandatory. It might be a good idea to use in your scenario, as it disables some defaults which make more sense when running as your default LDA.
I have the following python script
parser = argparse.ArgumentParser(description='Process controller.py arguments')
parser.add_argument("-b", help='Build number, e.g., 1234')
args = vars(parser.parse_args())
When I run it I get...
$ python CommandLineParser.py -h
usage: CommandLineParser.py [-h] [-b B]
Process controller.py arguments
optional arguments:
-h, --help show this help message and exit
-b B Build number, e.g., 1234
How do I make the "-b" show up as a "non-optional" argument (because it's NOT!). As an added bonus, how do I rid of the uppercase "B" after it? Thanks!
You need to set required to True and metavar (it's responsible for B) to '':
parser.add_argument("-b", help='Build number, e.g., 1234', required=True, metavar='')
Actually, you will still see your required argument as optional if run your script in a help mode. This is because of a bug: argparse required arguments displayed under "optional arguments":
The argparse module lists required args as optional in the default
help message.
There are also some workarounds suggested, but I like this one more: add your own required arguments group:
required_group = parser.add_argument_group('required arguments')
required_group.add_argument("-b", help='Build number, e.g., 1234', required=True, metavar='')
Then, you will see this on a command-line:
$ python test.py -h
usage: test.py [-h] -b
Process controller.py arguments
optional arguments:
-h, --help show this help message and exit
required arguments:
-b Build number, e.g., 1234
Please use the required keyword when adding it to the argparse: http://docs.python.org/2/library/argparse.html#sub-commands
parser.add_argument("-b", help='Build number, e.g., 1234', required=True)