Python3 - argparse switch and file - python

Hi I am trying to implement a small program which takes in 1 flag -s and a file
I would like to do the following:
When I want to sort:
$./my_program.py -s someFile.txt
when I dont want to sort:
$./my_program.py someFile.txt
Here is what I tried:
import argparse
parser = argparse.ArgumentParser(description='A tutorial of argparse!')
parser.add_argument("-s", default=False, type=bool, help="Is the DAG sorted? If yes, use the \'-s\' flag")
parser.add_argument('filename', help="Your database file")
args = parser.parse_args()
When I tried to run it from commandline I tried this:
my_program.py -s SortedDB.txt
I get:
error: the following arguments are required: filename
If I do this:
my_program.py -s filename SortedDB.txt
it works
or this:
iota_ledger_task.py iotaSortedDB.txt
it goes to the non sorted case (expected behavior), works.
What may I be doing wrong here?

You need action="store_true" instead type=bool
Documentation: Actions

Related

argparse: Why do I get "the following arguments are required"?

I am a beginner in programming, I am using the example
import argparse
import pandas as pd
def read_data(fname):
return pd.read_csv(fname)
if __name__ == "__main__":
options = argparse.ArgumentParser()
options.add_argument("-f", "--file", type=str, required=True)
args = options.parse_args()
data = read_data(args.file)
print(data)
I got this error:
error: the following arguments are required: -f/--file
Would you please help me how can define my file name, where to write it?
Thank you
With required=True, the command-line must include the -f or --file arguments:
# python myprog.py --file=somefile.txt
Make required=False
options.add_argument("-f", "--file", type=str, required=False)
Your original code would require yourprogram -f filename.csv where yourprogram is the name of your script file, and filename.csv is the name of a CSV file with input data. The -f option can also be spelled out in longhand as --file.
But options should typically be optional. Make this a regular required argument if it is mandatory.
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("file", type=str)
args = parser.parse_args()
data = read_data(args.file)
print(data)
Usage: yourprogram filename.csv
Perhaps you are using python yourprogram.py to run this script; then the usage would be python yourprogram.py filename.csv

`argparse` multiple choice argument?

I am using argparse to parse the Python command line which is supposed to look like this:
python script_name.py --sdks=first, second
My script looks like this:
sdk_choises = ['aio','sw']
parser = argparse.ArgumentParser(description='Blah blah')
parser.add_argument('--sdks', action='append', nargs='+', required=True, help='specifies target SDK(s)')
args = parser.parse_args()
if 'aio' in args.sdks:
# do something with aio
if 'sw' in args.sdks:
# do something with sw
When I execute:
python script_name.py --sdks=aio, sw I get error:
"usage: script.py [-h] --sdks SDKS [SDKS ...]
build.py: error: unrecognized arguments: sw"
I'd like to be able to choose one or all choices:
python script_name.py --sdks=first
python script_name.py --sdks=second
python script_name.py --sdks=first, second
Where did I go wrong?
The following works nice:
import argparse
parser = argparse.ArgumentParser(description='Blah blah')
parser.add_argument('--sdks', nargs='+', required=True, help='specifies target SDK(s)')
args = parser.parse_args()
print(args.sdks)
You don't need the = when passing options, just use:
$ python test.py --sdks ai pw
['ai', 'pw']
If you prefer your original form of the comma-separated list, plus check if the argument is valid, then I recommend:
parser.add_argument('--sdks', nargs=1, type=lambda s: [sdk_choises[sdk_choises.index(f)] for f in s.split(',')], ...
Even cleaner way is to define it in a separate function similar to lambda above:
parser.add_argument('--sdks', nargs=1, type=my_parse_function, ...
argparse docs has examples for the parsing function with proper error reporting.
With nargs=1 you'd need to remove one extra list layer.

python - is it possible to enter user-chosen input and output files

I'm a newbie in python, so please bear with me.
I don't know how to describe,so I'll just show an example.
python CODE.py -i1 input1.txt -i2 input2.txt -o output.txt
Is such thing possible with python? I've looked up for a while but haven't find an answer.
Thank you!
Instead of just linking to the argparse module or the argparse tutorial,
the other respondents probably should have just shown you how to do it:
import argparse
# Build the parser
p = argparse.ArgumentParser(prog='CODE.PY')
p.add_argument('-i1', type=argparse.FileType('r'),
metavar='sourcefile1', help='First input file')
p.add_argument('-i2', type=argparse.FileType('r'),
metavar='sourcefile2', help='Second input file')
p.add_argument('-o', type=argparse.FileType('w'),
metavar='destfile', help='Destination filename')
# Parse sys.argv
ns = p.parse_args()
# Use the files
data1 = ns.i1.read()
data2 = ns.i2.read()
result = data1[:10] + data2[:10]
ns.o.write(result)
A nice feature of argparse is that not only does it build parsers, it creates a nice option for command-line help:
$ python CODE.PY -h
usage: CODE.PY [-h] [-i1 sourcefile1] [-i2 sourcefile2] [-o destfile]
optional arguments:
-h, --help show this help message and exit
-i1 sourcefile1 First input file
-i2 sourcefile2 Second input file
-o destfile Destination filename
Yes, you can use system argument with your code.
Following snippet of code might help you to resolve your problem
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('inFile', nargs=2, help="Choose in file to use")
parser.add_argument('outFile', nargs=1, help="Choose out file to use")
args=parser.parse_args()
your_fun_call( args.inFile , args.outFile[0] )
Might look wierd at first look but you can refer this document
argparse
Note: infile argument has nargs as 2 because you want two input
files ( nargs stands for number of argument)
As thefourtheye said you can used argparse module. But if you want simple solution, just pass 2 inputs and output file paths as arguments to your executable and use sys.argv to get them in your program in order. The sys.argv[0] is your application name, sys.argv[1] is first input file path, sys.argv[2] is second input file path and sys.argv[3] is output file path.
import sys
input1 = sys.argv[1]
input2 = sys.argv[2]
output = sys.argv[3]
now you can call like below:
python my_app.py /path/to/input1.txt /path/to/input2.txt /path/to/output.txt

Pass a directory with argparse (no type checking needed)

I've written a file crawler and I'm trying to expand it. I want to use argparse to handle settings for the script including passing the starting directory in at the command line.
Example: /var/some/directory/
I have gotten several other arguments to work but I'm unable to pass this directory in correctly. I don't care if it's preceded by a flag or not, (e.g -d /path/to/start/) but I need to make sure that at the very least, this is argument is used as it will be the only mandatory option for the script to run.
Code Sample:
parser = argparse.ArgumentParser(description='py pub crawler...')
parser.add_argument('-v', '--verbose', help='verbose output from crawler', action="store_true")
parser.add_argument('-d', '--dump', help='dumps and replaces existing dictionaries', action="store_true")
parser.add_argument('-f', '--fake', help='crawl only, nothing stored to DB', action="store_true")
args = parser.parse_args()
if args.verbose:
verbose = True
if args.dump:
dump = True
if args.fake:
fake = True
Simply add:
parser.add_argument('directory',help='directory to use',action='store')
before your args = parser.parse_args() line. A simple test from the commandline shows that it does the right thing (printing args at the end of the script):
$ python test.py /foo/bar/baz
Namespace(directory='/foo/bar/baz', dump=False, fake=False, verbose=False)
$ python test.py
usage: test.py [-h] [-v] [-d] [-f] directory
test.py: error: too few arguments

Leave arguments untouched with argparse

I would like use argparse to parse the arguments that it knows and then leave the rest untouched. For example I want to be able to run
performance -o output other_script.py -a opt1 -b opt2
Which uses the -o option and leaves the rest untouched.
The module profiler.py does a similar thing with optparse, but since I'm using argparse I'm doing:
def parse_arguments():
parser = new_argument_parser('show the performance of the given run script')
parser.add_argument('-o', '--output', default='profiled.prof')
return parser.parse_known_args()
def main():
progname = sys.argv[1]
ns, other_args = parse_arguments()
sys.argv[:] = other_args
Which also seems to work, but what happens if also other_script.py also has a -o flag?
Is there in general a better way to solve this problem?
You could also add a positional argument to your parser with nargs=argparse.REMAINDER, to capture the script and its options:
# In script 'performance'...
p = argparse.ArgumentParser()
p.add_argument("-o")
p.add_argument("command", nargs=argparse.REMAINDER)
args = p.parse_args()
print args
Running the above minimal script...
$ performance -o output other_script.py -a opt1 -b opt2
Namespace(command=['performance', '-a', 'opt1', '-b', 'opt2'], o='output')
argparse will stop to parse argument until EOF or --. If you want to have argument without beeing parsed by argparse, you can write::
python [PYTHONOPTS] yourfile.py [YOURFILEOPT] -- [ANYTHINGELSE]

Categories

Resources