argparse - how to pass argument from args into function? - python

import argparse
from queries import most_common_cities
parser = argparse.ArgumentParser(description='A script that does operations with database data and returns values')
parser.add_argument('-c', '--most_common_cities',
nargs=1,
type=positive_int,
help='Specify how many common cities.')
args = parser.parse_args()
if args.most_common_cities:
result = most_common_cities(n) # "n" should be an arg passed by user
print(result)
How could I pass arguments from CLI to my function arg?
When someone use command:
python argp.py --most_common_cities 5
It should return 5 most common cities.

Remove nargs=1, then args.most_common_cities will be the actual value passed in.
nargs=1 wraps it in a list.
parser.add_argument('-c', '--most_common_cities',
type=int,
help='Specify how many common cities.')
args = parser.parse_args(['-c', '5'])
n = args.most_common_cities
print(n)
print(type(n))
# 5
# <class 'int'>

I started your script with following command:
python3 test.py --most_common_cities 5
You can access the arguments with:
import argparse
parser = argparse.ArgumentParser(description='A script that does operations with database data and returns values')
parser.add_argument('-c', '--most_common_cities',
nargs=1,
type=int,
help='Specify how many common cities.')
args = parser.parse_args()
arguments = vars(parser.parse_args())
print(arguments) #{'most_common_cities': [5]}
#then you can access the value with:
arguments['most_common_cities']

Related

Pass arguments via file and via command line [duplicate]

I want to launch my script like this:
python3 main.py #params.conf 1 2
where params.conf is a file and 1, 2 are string arguments.
I know how to parse file alone:
argparser = ArgumentParser()
argparser.add_argument('arg1', help='heeelp')
...
args = argparser.parse_args()
But how to parse following arguments?
An argument prefixed with # is treated as if its contents were in the command line directly, one argument per line. So if the contents of params.confis
2
3
And you define a parser like
import argparse
p = argparse.ArgumentParser(fromfile_prefix_chars='#')
p.add_argument("a")
p.add_argument("b")
p.add_argument("c")
p.add_argument("d")
args = p.parse_args()
and you call your script as
script.py 1 #params.conf 4
then your arguments a through d will be set to 1 through 4, respectively.
You just add more argparser.add_argument calls.
Like this:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('arg1', type=str)
parser.add_argument('arg2', type=str)
parser.add_argument('arg3', type=str)
args = parser.parse_args()
print(args) # arguments are parsed

python get changed (non-default) cli arguments?

Given an argument parser with n arguments, where I change the default value of only a small subset every run from the command line, is there a clean way of extracting a dict/namespace of all the non-default k,v arguments?
parser = argparse.ArgumentParser()
parser.add_argument("--a",type=str,default='a')
parser.add_argument("--b",type=str,default='b')
parser.add_argument("--c",type=str,default='c')
parser.add_argument("--d",type=str,default='d')
And
python run.py --a "e"
I would like to have
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--a",type=str,default='a')
parser.add_argument("--b",type=str,default='b')
parser.add_argument("--c",type=str,default='c')
parser.add_argument("--d",type=str,default='d')
non_default = parse_non_default(parser) # non_default = {'a':'e'}
You could lookup the parser and compare which values differenciate:
import argparse
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--a", type=str, default='a')
parser.add_argument("--b", type=str, default='b')
parser.add_argument("--c", type=str, default='c')
parser.add_argument("--d", type=str, default='d')
parser.add_argument("--n", type=int, default=999)
args = parser.parse_args(['--a', 'e']) # Test CLI arguments!
non_default = {
opt.dest: getattr(args, opt.dest)
for opt in parser._option_string_actions.values()
if hasattr(args, opt.dest) and opt.default != getattr(args, opt.dest)
}
print(non_default)
main()
Out:
{'a': 'e'}

How to run a python script inside a python script

I have a Python script script1 that have multiple arguments which could be simplified as:
def add_vars(var1, var2, var3, var4, var5):
sum = var1+var2+var3+var4+var5
return sum
if __name__ == '__main__':
parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter, description="""
simple addition
""")
parser.add_argument('var1', type=float, help='var1')
parser.add_argument('-var2', type=float, default=20, help='var2')
parser.add_argument('-var3', type=float, default=30, help='var3')
parser.add_argument('-var4', type=float, default=40, help='var4')
parser.add_argument('-var5', type=float, default=50, help='var5')
args = parser.parse_args()
print(args)
ss = add_vars(args.var1, args.var2, args.var3, args.var4, args.var5)
print('sum=', ss)
in which only arg1 is required and arg2-arg5 are optional.
I would like to call this script in another Python script with arg1, arg3 just like in the terminal:
script1.py 1 -var3 4
Does anyone know how to do this? I have tried os.execl but without luck.
EDIT: I'd say using subprocess wouldn't be a "better" way but this is a way you could do it?
from subprocess import check_output
out = check_output(["python", "script1.py", "1", "-var3", "4"])
print(out.decode("utf-8"))
Output:
Namespace(var1=1.0, var2=20, var3=4.0, var4=40, var5=50)
sum= 115.0
<empty line>
Original:
script1.py:
def add_vars(var1, var2=20, var3=30, var4=40, var5=50):
sum = var1+var2+var3+var4+var5
return sum
if __name__ == '__main__':
parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter,
description="""simple addition""")
parser.add_argument('var1', type=float, help='var1')
parser.add_argument('-var2', type=float, default=20, help='var2')
parser.add_argument('-var3', type=float, default=30, help='var3')
parser.add_argument('-var4', type=float, default=40, help='var4')
parser.add_argument('-var5', type=float, default=50, help='var5')
args = parser.parse_args()
print(args)
ss = add_vars(args.var1, args.var2, args.var3, args.var4, args.var5)
print('sum=', ss)
script2.py:
import script1
print(script1.add_vars(1, var3=4))
var2=20, var3=30, var4=40, var5=50 sets the default values for the function (just like for argparse)
if __name__=='__main__'
resists your program functions to be called in other program
so you can do something like this in in other program
from script1.py import add_vars
and since you have given arg 1 and 3 default vals in the function you with other arguments so you have to be careful while passing other args , while you are in the other file
add_vars(arg1,arg3)
if you would have simply call script1.py then this would have not executed
if you have further question do add a comment i'll do make my best to answer your query
if you want to change vals of arg1 and arg3
add_vars(arg1=29,arg3=8)
you can specify them ,
so that their default value is overrided

Argparse arguments from file and string CLI arguments both

I want to launch my script like this:
python3 main.py #params.conf 1 2
where params.conf is a file and 1, 2 are string arguments.
I know how to parse file alone:
argparser = ArgumentParser()
argparser.add_argument('arg1', help='heeelp')
...
args = argparser.parse_args()
But how to parse following arguments?
An argument prefixed with # is treated as if its contents were in the command line directly, one argument per line. So if the contents of params.confis
2
3
And you define a parser like
import argparse
p = argparse.ArgumentParser(fromfile_prefix_chars='#')
p.add_argument("a")
p.add_argument("b")
p.add_argument("c")
p.add_argument("d")
args = p.parse_args()
and you call your script as
script.py 1 #params.conf 4
then your arguments a through d will be set to 1 through 4, respectively.
You just add more argparser.add_argument calls.
Like this:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('arg1', type=str)
parser.add_argument('arg2', type=str)
parser.add_argument('arg3', type=str)
args = parser.parse_args()
print(args) # arguments are parsed

Python argparse: nargs + or * depending on prior argument

I'm writing a server querying tool, and I have a little bit of code to parse arguments at the very top:
# Parse arguments
p = argparse.ArgumentParser()
g = p.add_mutually_exclusive_group(required=True)
g.add_argument('--odam', dest='query_type', action='store_const',
const='odam', help="Odamex Master query.")
g.add_argument('--odas', dest='query_type', action='store_const',
const='odas', help="Odamex Server query.")
p.add_argument('address', nargs='*')
args = p.parse_args()
# Default master server arguments.
if args.query_type == 'odam' and not args.address:
args.address = [
'master1.odamex.net:15000',
'master2.odamex.net:15000',
]
# If we don't have any addresses by now, we can't go on.
if not args.address:
print "If you are making a server query, you must pass an address."
sys.exit(1)
Is there a nicer way to do this, preferably all within the parser? That last error looks a little out of place, and it would be nice if I could make nargs for address depend on if --odam or ---odas is passed. I could create a subparser, but that would make help look a little odd since it would leave off the addresses part of the command.
You can do this with an custom argparse.Action:
import argparse
import sys
class AddressAction(argparse.Action):
def __call__(self, parser, args, values, option = None):
args.address=values
if args.query_type=='odam' and not args.address:
args.address=[
'master1.odamex.net:15000',
'master2.odamex.net:15000',
]
if not args.address:
parser.error("If you are making a server query, you must pass an address.")
p = argparse.ArgumentParser()
g = p.add_mutually_exclusive_group(required=True)
g.add_argument('--odam', dest='query_type', action='store_const',
const='odam', help="Odamex Master query.")
g.add_argument('--odas', dest='query_type', action='store_const',
const='odas', help="Odamex Server query.")
p.add_argument('address', nargs='*', action=AddressAction)
args = p.parse_args()
yields
% test.py --odas
If you are making a server query, you must pass an address.
% test.py --odam
Namespace(address=['master1.odamex.net:15000', 'master2.odamex.net:15000'], query_type='odam')
% test.py --odam 1 2 3
Namespace(address=['1', '2', '3'], query_type='odam')

Categories