I am developing an application taking input from the user (path) and using it later however some problems when the path had special characters like % for example (C:\path%25 -> C C:\path5)
Is there any way to stop the parser from applying the skipping characters?
Am using the following code:
parser = argparse.ArgumentParser(description='test', formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('-p', '--path', help='Specifies the input path', nargs="*", dest='path', required=True, type=str)
args = parser.parse_args()
print(args.path)
Related
I am using argparse for command line arguments, where one argument is one or more .csv files:
parser = argparse.ArgumentParser(description='...')
parser.add_argument('csv', type=str, nargs='+', help='.csv file(s)'))
parser.add_argument('days', type=int, help='Number of days'))
args = parser.parse_args()
print(args.csv)
When running $ python Filename.py csv Filename.csv days 30, args.csv is ['csv', 'Filename.csv', 'days'], but I don't want to be capturing the csv and days arguments which surround the input csv files.
You can use
import argparse
parser = argparse.ArgumentParser(description='...')
parser.add_argument("csv", type=str, nargs='+', help='.csv file(s)')
parser.add_argument("days", type=int, help='Number of days')
args = parser.parse_args()
print(args.csv)
Invoked with e.g. python your_script.py test.csv 100 this yields
['test.csv']
Note that you do not need to encapsulate parser.add_argument(...) twice (as you had in your code).
In argparse, I want to prevent a particular combination of arguments. Lets see the sample code.
Sample:
import argparse
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument('--firstname', dest='fn', action='store')
parser.add_argument('--lastname', dest='ln', action='store')
parser.add_argument('--fullname', dest='full', action='store')
args = parser.parse_args()
For eg: --firstname --lastname --fullname
The user can run the code in 2 days.
Way 1:
code.py --firstname myfirst --lastname mylast
Way 2:
code.py --fullname myfullname
Prevent
We should not use the combination fistname, fullname or lastname, fullname. If we use both, then it should not execute.
Can someone help me to fix this?
Not sure that is an argparse specific behavior that is possible. But as long as those items are going to their own variables in the argparse resposes its a simple set of programming to check which ones are set and issue a message and exit.
example (assuming the result of parsing is in argsvalue):
if argsvalue.fullname and (argsvalue.firstname or argsvalue.lastname):
print ("missuse of name options.....")
This assumes the argparse default for the vars is None (then if anything is set in them they will test to true with the logic above...
Like this answer proposes (on a similar question) you can do something like the following by using subparsers for both cases:
# create the top-level parser
parser = argparse.ArgumentParser(add_help=false)
subparsers = parser.add_subparsers(help='help for subcommands')
# create the parser for the "full_name" command
full_name = subparsers.add_parser('full_name', help='full_name help')
full_name.add_argument('--fullname', dest='full', action='store')
# create the parser for the "separate_names" command
separate_names = subparsers.add_parser('separate_names', help='separate_names help')
separate_names.add_argument('--firstname', dest='fn', action='store')
separate_names.add_argument('--lastname', dest='ln', action='store')
args = parser.parse_args()
You can improve it even further by requiring both the first and last name of the user as it generally makes sense.
You can split your arguments into separate commands and use subparsers, for example:
import argparse
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
parser_clean = subparsers.add_parser('clean', description='clean build folder')
parser_clean.add_argument('--all', help='clean build folder and logs', action='store_true')
parser_deploy = subparsers.add_parser('deploy')
parser_deploy.add_argument('object')
parser_deploy.add_argument('--nc', help='no cleanup', action='store_true')
args = parser.parse_args()
I would like to execute a code which is accessible from this link.
The code objective is to read and extract the pdf annotation.
However, I am not sure how to direct the pdf file path using the argparse, which I suspect, should be the following argparse.
p.add_argument("input", metavar="INFILE", type=argparse.FileType("rb"),
help="PDF files to process", nargs='+')
Say, I know the absolute path of the pdf file is as follow;
C:\abc.pdf
Also, given that I still try to comprehend the code, so I would like to avoid re-enter the path C:\abc.pdf over and over again. Is there are way, I can temporary hard coded it within the def parse_args()
I have read several thread about this topic, however, still having difficulties in comprehend about this issue.
Thanks in advance for any insight.
You add the argument to a parser:
import argparse
p = argparse.ArgumentParser()
p.add_argument("input", metavar="INFILE", type=argparse.FileType("rb"),
help="PDF files to process", nargs='+')
args = p.parse_args()
Then args.input will be a tuple of one or more open file handles.
If you're running pdfannots.py from the command prompt, then you do so as, e.g.,
python pdfannots.py C:\abc.pdf
If you want to run it over multiple PDF files, then you do so as, e.g.,
python pdfannots.py C:\abc.pdf D:\xyz.pdf E:\foo.pdf
If you really want to hard code the path, you'll have to edit pdfannots.py as follows:
def parse_args():
p = argparse.ArgumentParser(description=__doc__)
# p.add_argument("input", metavar="INFILE", type=argparse.FileType("rb"),
# help="PDF files to process", nargs='+')
g = p.add_argument_group('Basic options')
g.add_argument("-p", "--progress", default=False, action="store_true",
help="emit progress information")
g.add_argument("-o", metavar="OUTFILE", type=argparse.FileType("w"), dest="output",
default=sys.stdout, help="output file (default is stdout)")
g.add_argument("-n", "--cols", default=2, type=int, metavar="COLS", dest="cols",
help="number of columns per page in the document (default: 2)")
g = p.add_argument_group('Options controlling output format')
allsects = ["highlights", "comments", "nits"]
g.add_argument("-s", "--sections", metavar="SEC", nargs="*",
choices=allsects, default=allsects,
help=("sections to emit (default: %s)" % ', '.join(allsects)))
g.add_argument("--no-group", dest="group", default=True, action="store_false",
help="emit annotations in order, don't group into sections")
g.add_argument("--print-filename", dest="printfilename", default=False, action="store_true",
help="print the filename when it has annotations")
g.add_argument("-w", "--wrap", metavar="COLS", type=int,
help="wrap text at this many output columns")
return p.parse_args()
def main():
args = parse_args()
global COLUMNS_PER_PAGE
COLUMNS_PER_PAGE = args.cols
for file in [open(r"C:\Users\jezequiel\Desktop\Timeline.pdf", "rb")]:
(annots, outlines) = process_file(file, args.progress)
pp = PrettyPrinter(outlines, args.wrap)
if args.printfilename and annots:
print("# File: '%s'\n" % file.name)
if args.group:
pp.printall_grouped(args.sections, annots, args.output)
else:
pp.printall(annots, args.output)
return 0
Here's what I'm trying to accomplish:
When passing a string as the arg, call a write_text() function
python3 app.py write this text to file
When passing a dashed arg, call another function, in this case read_text()
python3 app.py -r
When passing no args print help
python3 app.py
Here's what I have so far:
parser = argparse.ArgumentParser()
parser.add_argument('text', help="write text to file")
parser.add_argument('-r', '--read', help="read text from file")
args = parser.parse_args()
...
def main():
if args.read:
read_text()
elif args.text:
write_text(args.text)
else:
parser.print_help()
The problem is that when I call just -r it complains that it's missing a command for text, because text is not an optional argument.
I've tried creating subcommands and making all the args subcommands but then the text argument needs to be explicitly called like python3 app.py text.
I may be thinking too hard on this and overlooking a simple solution. I had this working perfectly just parsing sys.argv, but it wasn't pretty. And the built in help function is useful as well.
Thanks in advance!
Edit:
Here's what I have now that's working
parser = argparse.ArgumentParser()
parser.add_argument('text', nargs='*', help="write text to file")
parser.add_argument('-r', '--read', action='store_true', help="read text from file")
args = parser.parse_args()
...
def main():
if args.read:
read_text()
elif args.text:
text = " ".join(args.text)
write_text(text)
else:
parser.print_help()
Still thinking there may be a cleaner way to do this...
This might help :
parser.add_argument('text', nargs='?', help="write text to file")
more info : https://docs.python.org/3/library/argparse.html#nargs
Note that you should use action='store_true' for the read argument if you want to use args.read as a boolean later.
parser.add_argument('-r', '--read', action='store_true', help="read text from file")
I want to have some options in argparse module such as --pm-export however when I try to use it like args.pm-export I get the error that there is not attribute pm. How can I get around this issue? Is it possible to have - in command line options?
As indicated in the argparse docs:
For optional argument actions, the value of dest is normally inferred from the option strings. ArgumentParser generates the value of dest by taking the first long option string and stripping away the initial -- string. Any internal - characters will be converted to _ characters to make sure the string is a valid attribute name
So you should be using args.pm_export.
Unfortunately, dash-to-underscore replacement doesn't work for positional arguments (not prefixed by --).
E.g:
parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('logs-dir',
help='Directory with .log and .log.gz files')
parser.add_argument('results-csv', type=argparse.FileType('w'),
default=sys.stdout,
help='Output .csv filename')
args = parser.parse_args()
print args
# gives
# Namespace(logs-dir='./', results-csv=<open file 'lool.csv', mode 'w' at 0x9020650>)
So, you should use 1'st argument to add_argument() as attribute name and metavar kwarg to set how it should look in help:
parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('logs_dir', metavar='logs-dir',
nargs=1,
help='Directory with .log and .log.gz files')
parser.add_argument('results_csv', metavar='results-csv',
nargs=1,
type=argparse.FileType('w'),
default=sys.stdout,
help='Output .csv filename')
args = parser.parse_args()
print args
# gives
# Namespace(logs_dir=['./'], results_csv=[<open file 'lool.csv', mode 'w' at 0xb71385f8>])
Dashes are converted to underscores:
import argparse
pa = argparse.ArgumentParser()
pa.add_argument('--foo-bar')
args = pa.parse_args(['--foo-bar', '24'])
print args # Namespace(foo_bar='24')
Concise and explicit but probably not always acceptable way would be to use vars():
#!/usr/bin/env python3
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('a-b')
args = vars(parser.parse_args())
print(args['a-b'])
getattr(args, 'positional-arg')
This is another OK workaround for positional arguments:
#!/usr/bin/env python3
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('a-b')
args = parser.parse_args(['123'])
assert getattr(args, 'a-b') == '123'
Tested on Python 3.8.2.
I guess the last option is to change shorten option -a to --a
import argparse
parser = argparse.ArgumentParser(description="Help")
parser.add_argument("--a", "--argument-option", metavar="", help="") # change here
args = parser.parse_args()
option = args.a # And here
print(option)