I have a small python script, which uses argparse to let the user define options. It uses two flags for different modes and an argument to let the user define a file. See the simplified example below:
#!/usr/bin/python3
import argparse
from shutil import copyfile
def check_file(f):
# Mock function: checks if file exists, else "argparse.ArgumentTypeError("file not found")"
return f
def main():
aFile = "/tmp/afile.txt"
parser = argparse.ArgumentParser(description="An example",formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument("-f", "--file", help="A file, used with method A.", default=aFile, type=check_file)
parser.add_argument("-a", "--ay", help="Method A, requires file.", action='store_true')
parser.add_argument("-b", "--be", help="Method B, no file required.", action='store_true')
args = parser.parse_args()
f = args.file
a = args.ay
b = args.be
if a:
copyfile(f, f+".a")
elif b:
print("Method B")
if __name__ == "__main__":
main()
Method A requires the file.
Method B does not.
If I run the script with method A, I either use the default file or one that is defined with -f/--file. The script checks if the file exists and everything is fine.
Now, if I run the script with method B, it shouldn't require the file, but the default option is checked and if it doesn't exist the argparse function raises the exception and the script exits.
How can I configure argparse to make -f optional, if -b is defined and require it, if -a is defined?
edit: I just realized that it would be enough for me to make -f and -b mutually exclusive. But then, if I run -b only, the check_file is executed anyways. Is there a way to prevent that?
#!/usr/bin/python3
import argparse
from shutil import copyfile
def check_file(f):
# Mock function: checks if file exists, else "argparse.ArgumentTypeError("file not found")"
print("chk file")
return f
def main():
aFile = "/tmp/afile.txt"
parser = argparse.ArgumentParser(description="An example",formatter_class=argparse.RawTextHelpFormatter)
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument("-f", "--file", help="A file, used with method A.", default=aFile, type=check_file)
parser.add_argument("-a", "--ay", help="Method A, requires file.", action='store_true')
group.add_argument("-b", "--be", help="Method B, no file required.", action='store_true')
args = parser.parse_args()
f = args.file
a = args.ay
b = args.be
if a:
print("File: "+str(f))
elif b:
print("Method B")
print("file: "+str(f))
if __name__ == "__main__":
main()
Output:
chk file
Method B
file: /tmp/afile.txt
4466197is a poor answer for this case. 'groups' are not designed for nesting, and they don't solve the 'default' evaluation problem here.