Python CLI-Parser improvement for “one of those options”
up vote
2
down vote
favorite
I was wondering if there was a better way to implement my cli parser.
For context:
I need to pass to my script either a file in one of two formats or two files in a specific format.
It may be easier to understand like this:
file.ext1 OR file.ext2 OR (file_1.ext2 AND file_2.ext2)
I've used python argparse add_mutually_exclusive_group
successfully and it looks like this:
import argparse
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument(
"--ext1",
type = __existant_file,
metavar = "FILE",
help = "input file (format ext1)"
)
group.add_argument(
"--ext2",
type = __existant_file,
metavar = "FILE",
help = "input file (format ext2)"
)
group.add_argument(
"--paired",
nargs = 2,
type = __existant_file,
metavar = ("MATE_1", "MATE_2"),
help = "input file (two files format ext2)"
)
args = parser.parse_args()
print(args)
if args.ext1 is not None:
file = args.ext1
elif args.ext2 is not None:
file = args2.ext2
else:
file = args.paired[0]
file2 = args.paired[1]
Which is used as:
python script.py --ext1 file
OR
python script.py --ext2 file
OR
python script.py --paired file_1 file_2
Which is working but not really smooth. Do you have any lead of how I can improve the CLI parser ?
python console
add a comment |
up vote
2
down vote
favorite
I was wondering if there was a better way to implement my cli parser.
For context:
I need to pass to my script either a file in one of two formats or two files in a specific format.
It may be easier to understand like this:
file.ext1 OR file.ext2 OR (file_1.ext2 AND file_2.ext2)
I've used python argparse add_mutually_exclusive_group
successfully and it looks like this:
import argparse
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument(
"--ext1",
type = __existant_file,
metavar = "FILE",
help = "input file (format ext1)"
)
group.add_argument(
"--ext2",
type = __existant_file,
metavar = "FILE",
help = "input file (format ext2)"
)
group.add_argument(
"--paired",
nargs = 2,
type = __existant_file,
metavar = ("MATE_1", "MATE_2"),
help = "input file (two files format ext2)"
)
args = parser.parse_args()
print(args)
if args.ext1 is not None:
file = args.ext1
elif args.ext2 is not None:
file = args2.ext2
else:
file = args.paired[0]
file2 = args.paired[1]
Which is used as:
python script.py --ext1 file
OR
python script.py --ext2 file
OR
python script.py --paired file_1 file_2
Which is working but not really smooth. Do you have any lead of how I can improve the CLI parser ?
python console
@Graipher Well, I do believe this is exactly what I asked, my code is working but I'd like improvement. Maybe it's not clear tho, I'll rewrite a bit
– Plopp
Sep 4 at 14:03
2
@Graipher Oh I didn't though I needed a working example as I wasn't expecting any code back but more a general idea, I've edited it :)
– Plopp
Sep 4 at 14:20
1
We got a very good meta thread about how to improve question quality if you're interested :-)
– Mast
Sep 4 at 14:31
depending on the specific case, a simpler cli interface might be preferable: just pass one or two files as positional parameters (raise ArgumentError if given files in a wrong format). Usingdocopt
, you would specify the alternatives on two/three lines. Here's a variant with the two line usage:command <file.ext1>
$command <file1.ext2> [<file2.ext2>]
– jfs
Sep 4 at 19:05
add a comment |
up vote
2
down vote
favorite
up vote
2
down vote
favorite
I was wondering if there was a better way to implement my cli parser.
For context:
I need to pass to my script either a file in one of two formats or two files in a specific format.
It may be easier to understand like this:
file.ext1 OR file.ext2 OR (file_1.ext2 AND file_2.ext2)
I've used python argparse add_mutually_exclusive_group
successfully and it looks like this:
import argparse
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument(
"--ext1",
type = __existant_file,
metavar = "FILE",
help = "input file (format ext1)"
)
group.add_argument(
"--ext2",
type = __existant_file,
metavar = "FILE",
help = "input file (format ext2)"
)
group.add_argument(
"--paired",
nargs = 2,
type = __existant_file,
metavar = ("MATE_1", "MATE_2"),
help = "input file (two files format ext2)"
)
args = parser.parse_args()
print(args)
if args.ext1 is not None:
file = args.ext1
elif args.ext2 is not None:
file = args2.ext2
else:
file = args.paired[0]
file2 = args.paired[1]
Which is used as:
python script.py --ext1 file
OR
python script.py --ext2 file
OR
python script.py --paired file_1 file_2
Which is working but not really smooth. Do you have any lead of how I can improve the CLI parser ?
python console
I was wondering if there was a better way to implement my cli parser.
For context:
I need to pass to my script either a file in one of two formats or two files in a specific format.
It may be easier to understand like this:
file.ext1 OR file.ext2 OR (file_1.ext2 AND file_2.ext2)
I've used python argparse add_mutually_exclusive_group
successfully and it looks like this:
import argparse
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument(
"--ext1",
type = __existant_file,
metavar = "FILE",
help = "input file (format ext1)"
)
group.add_argument(
"--ext2",
type = __existant_file,
metavar = "FILE",
help = "input file (format ext2)"
)
group.add_argument(
"--paired",
nargs = 2,
type = __existant_file,
metavar = ("MATE_1", "MATE_2"),
help = "input file (two files format ext2)"
)
args = parser.parse_args()
print(args)
if args.ext1 is not None:
file = args.ext1
elif args.ext2 is not None:
file = args2.ext2
else:
file = args.paired[0]
file2 = args.paired[1]
Which is used as:
python script.py --ext1 file
OR
python script.py --ext2 file
OR
python script.py --paired file_1 file_2
Which is working but not really smooth. Do you have any lead of how I can improve the CLI parser ?
python console
python console
edited Sep 4 at 14:22
asked Sep 4 at 13:57
Plopp
112
112
@Graipher Well, I do believe this is exactly what I asked, my code is working but I'd like improvement. Maybe it's not clear tho, I'll rewrite a bit
– Plopp
Sep 4 at 14:03
2
@Graipher Oh I didn't though I needed a working example as I wasn't expecting any code back but more a general idea, I've edited it :)
– Plopp
Sep 4 at 14:20
1
We got a very good meta thread about how to improve question quality if you're interested :-)
– Mast
Sep 4 at 14:31
depending on the specific case, a simpler cli interface might be preferable: just pass one or two files as positional parameters (raise ArgumentError if given files in a wrong format). Usingdocopt
, you would specify the alternatives on two/three lines. Here's a variant with the two line usage:command <file.ext1>
$command <file1.ext2> [<file2.ext2>]
– jfs
Sep 4 at 19:05
add a comment |
@Graipher Well, I do believe this is exactly what I asked, my code is working but I'd like improvement. Maybe it's not clear tho, I'll rewrite a bit
– Plopp
Sep 4 at 14:03
2
@Graipher Oh I didn't though I needed a working example as I wasn't expecting any code back but more a general idea, I've edited it :)
– Plopp
Sep 4 at 14:20
1
We got a very good meta thread about how to improve question quality if you're interested :-)
– Mast
Sep 4 at 14:31
depending on the specific case, a simpler cli interface might be preferable: just pass one or two files as positional parameters (raise ArgumentError if given files in a wrong format). Usingdocopt
, you would specify the alternatives on two/three lines. Here's a variant with the two line usage:command <file.ext1>
$command <file1.ext2> [<file2.ext2>]
– jfs
Sep 4 at 19:05
@Graipher Well, I do believe this is exactly what I asked, my code is working but I'd like improvement. Maybe it's not clear tho, I'll rewrite a bit
– Plopp
Sep 4 at 14:03
@Graipher Well, I do believe this is exactly what I asked, my code is working but I'd like improvement. Maybe it's not clear tho, I'll rewrite a bit
– Plopp
Sep 4 at 14:03
2
2
@Graipher Oh I didn't though I needed a working example as I wasn't expecting any code back but more a general idea, I've edited it :)
– Plopp
Sep 4 at 14:20
@Graipher Oh I didn't though I needed a working example as I wasn't expecting any code back but more a general idea, I've edited it :)
– Plopp
Sep 4 at 14:20
1
1
We got a very good meta thread about how to improve question quality if you're interested :-)
– Mast
Sep 4 at 14:31
We got a very good meta thread about how to improve question quality if you're interested :-)
– Mast
Sep 4 at 14:31
depending on the specific case, a simpler cli interface might be preferable: just pass one or two files as positional parameters (raise ArgumentError if given files in a wrong format). Using
docopt
, you would specify the alternatives on two/three lines. Here's a variant with the two line usage: command <file.ext1>
$ command <file1.ext2> [<file2.ext2>]
– jfs
Sep 4 at 19:05
depending on the specific case, a simpler cli interface might be preferable: just pass one or two files as positional parameters (raise ArgumentError if given files in a wrong format). Using
docopt
, you would specify the alternatives on two/three lines. Here's a variant with the two line usage: command <file.ext1>
$ command <file1.ext2> [<file2.ext2>]
– jfs
Sep 4 at 19:05
add a comment |
1 Answer
1
active
oldest
votes
up vote
0
down vote
Okay, I found a better way
import argparse
parser = argparse.ArgumentParser()
class RequiredLen(argparse.Action):
def __call__(self, parser, args, values, option_string=None):
if not 1 <= len(values) <= 2:
msg = f"argument {self.dest} requires 1 or 2 arguments"
raise argparse.ArgumentTypeError(msg)
setattr(args, self.dest, values)
# Just give me 1 or 2 files
parser.add_argument(
"--paired",
nargs = '+',
action = RequiredLen,
required = True,
help = "input file(s)"
)
# Specify either ext1 or ext2 format
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument(
"--ext1",
action = "store_const",
dest = "format",
const = "ext1",
help = "input is ext1 format"
)
group.add_argument(
"--ext2",
action = "store_const",
dest = "format",
const = "ext2",
help = "input is ext2 format"
)
args = parser.parse_args()
print(args)
This way I can later just use something like:
def process_ext1(l: list):
print("ext1 file(s)")
for i in l:
print(i)
def process_ext2(l: list):
print("ext2 file(s)")
for i in l:
print(i)
process_format = { 'ext1': process_ext1, 'ext2': process_ext2 }
process_format[args.format](args.paired)
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
Okay, I found a better way
import argparse
parser = argparse.ArgumentParser()
class RequiredLen(argparse.Action):
def __call__(self, parser, args, values, option_string=None):
if not 1 <= len(values) <= 2:
msg = f"argument {self.dest} requires 1 or 2 arguments"
raise argparse.ArgumentTypeError(msg)
setattr(args, self.dest, values)
# Just give me 1 or 2 files
parser.add_argument(
"--paired",
nargs = '+',
action = RequiredLen,
required = True,
help = "input file(s)"
)
# Specify either ext1 or ext2 format
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument(
"--ext1",
action = "store_const",
dest = "format",
const = "ext1",
help = "input is ext1 format"
)
group.add_argument(
"--ext2",
action = "store_const",
dest = "format",
const = "ext2",
help = "input is ext2 format"
)
args = parser.parse_args()
print(args)
This way I can later just use something like:
def process_ext1(l: list):
print("ext1 file(s)")
for i in l:
print(i)
def process_ext2(l: list):
print("ext2 file(s)")
for i in l:
print(i)
process_format = { 'ext1': process_ext1, 'ext2': process_ext2 }
process_format[args.format](args.paired)
add a comment |
up vote
0
down vote
Okay, I found a better way
import argparse
parser = argparse.ArgumentParser()
class RequiredLen(argparse.Action):
def __call__(self, parser, args, values, option_string=None):
if not 1 <= len(values) <= 2:
msg = f"argument {self.dest} requires 1 or 2 arguments"
raise argparse.ArgumentTypeError(msg)
setattr(args, self.dest, values)
# Just give me 1 or 2 files
parser.add_argument(
"--paired",
nargs = '+',
action = RequiredLen,
required = True,
help = "input file(s)"
)
# Specify either ext1 or ext2 format
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument(
"--ext1",
action = "store_const",
dest = "format",
const = "ext1",
help = "input is ext1 format"
)
group.add_argument(
"--ext2",
action = "store_const",
dest = "format",
const = "ext2",
help = "input is ext2 format"
)
args = parser.parse_args()
print(args)
This way I can later just use something like:
def process_ext1(l: list):
print("ext1 file(s)")
for i in l:
print(i)
def process_ext2(l: list):
print("ext2 file(s)")
for i in l:
print(i)
process_format = { 'ext1': process_ext1, 'ext2': process_ext2 }
process_format[args.format](args.paired)
add a comment |
up vote
0
down vote
up vote
0
down vote
Okay, I found a better way
import argparse
parser = argparse.ArgumentParser()
class RequiredLen(argparse.Action):
def __call__(self, parser, args, values, option_string=None):
if not 1 <= len(values) <= 2:
msg = f"argument {self.dest} requires 1 or 2 arguments"
raise argparse.ArgumentTypeError(msg)
setattr(args, self.dest, values)
# Just give me 1 or 2 files
parser.add_argument(
"--paired",
nargs = '+',
action = RequiredLen,
required = True,
help = "input file(s)"
)
# Specify either ext1 or ext2 format
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument(
"--ext1",
action = "store_const",
dest = "format",
const = "ext1",
help = "input is ext1 format"
)
group.add_argument(
"--ext2",
action = "store_const",
dest = "format",
const = "ext2",
help = "input is ext2 format"
)
args = parser.parse_args()
print(args)
This way I can later just use something like:
def process_ext1(l: list):
print("ext1 file(s)")
for i in l:
print(i)
def process_ext2(l: list):
print("ext2 file(s)")
for i in l:
print(i)
process_format = { 'ext1': process_ext1, 'ext2': process_ext2 }
process_format[args.format](args.paired)
Okay, I found a better way
import argparse
parser = argparse.ArgumentParser()
class RequiredLen(argparse.Action):
def __call__(self, parser, args, values, option_string=None):
if not 1 <= len(values) <= 2:
msg = f"argument {self.dest} requires 1 or 2 arguments"
raise argparse.ArgumentTypeError(msg)
setattr(args, self.dest, values)
# Just give me 1 or 2 files
parser.add_argument(
"--paired",
nargs = '+',
action = RequiredLen,
required = True,
help = "input file(s)"
)
# Specify either ext1 or ext2 format
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument(
"--ext1",
action = "store_const",
dest = "format",
const = "ext1",
help = "input is ext1 format"
)
group.add_argument(
"--ext2",
action = "store_const",
dest = "format",
const = "ext2",
help = "input is ext2 format"
)
args = parser.parse_args()
print(args)
This way I can later just use something like:
def process_ext1(l: list):
print("ext1 file(s)")
for i in l:
print(i)
def process_ext2(l: list):
print("ext2 file(s)")
for i in l:
print(i)
process_format = { 'ext1': process_ext1, 'ext2': process_ext2 }
process_format[args.format](args.paired)
answered Sep 4 at 16:01
Plopp
112
112
add a comment |
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f203104%2fpython-cli-parser-improvement-for-one-of-those-options%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
@Graipher Well, I do believe this is exactly what I asked, my code is working but I'd like improvement. Maybe it's not clear tho, I'll rewrite a bit
– Plopp
Sep 4 at 14:03
2
@Graipher Oh I didn't though I needed a working example as I wasn't expecting any code back but more a general idea, I've edited it :)
– Plopp
Sep 4 at 14:20
1
We got a very good meta thread about how to improve question quality if you're interested :-)
– Mast
Sep 4 at 14:31
depending on the specific case, a simpler cli interface might be preferable: just pass one or two files as positional parameters (raise ArgumentError if given files in a wrong format). Using
docopt
, you would specify the alternatives on two/three lines. Here's a variant with the two line usage:command <file.ext1>
$command <file1.ext2> [<file2.ext2>]
– jfs
Sep 4 at 19:05