I am trying to run code using user's args as:
parser = argparse.ArgumentParser()
args = parser.parse_args()
parser = argparse.ArgumentParser(description='Script for running daily batch jobs for T3000 Project')
parser.add_argument("from_date", help='date in string yyyy-mm-dd', default='2017-10-1')
parser.add_argument("to_date", help='date in string yyyy-mm-dd', default='2017-12-31')
args = parser.parse_args()
main(
from_date=args.from_date,
to_date=args.to_date
)
While passing the arguments, I am following the path in Pycharm as: Run->Edit Configurations->Script Parameters: "2017-10-31" "2017-11-1"
I am getting error:
driver.py: error: unrecognized arguments: 2017-10-31 2017-11-1
Process finished with exit code 2
I have seen the link, which seems similar to my problem, but given solution didn't work for me. I am missing something I guess. Help will be appreciated.
Your first argument parser:
parser = argparse.ArgumentParser()
args = parser.parse_args()
is expecting no arguments, but you have passed in two. That is where the complaint is coming from. The solution is simply to remove those two lines - I don't know why you have them there in the first place.
I dont understand the comment by #lxop, I had the same error but I require both these lines. My code is the same apart from variables as the code used in the original question.
The solution for me is to set up my parameter in Pycharm as follows, quotations around the parameter are optional. I get the error when -o is missing.
-o filename.csv
My argparse setup line is
parser.add_argument("-o", "--outfile",
help="Enter the name of a .csv file to contain output or default of radarOutTemp.csv will be used",
default="radarOutTemp.csv")
Related
I have a .py file following the normal code structure
def main( args ):
.......
.......
if __name__ == "__main__":
parser = argparse.ArgumentParser(description = “ forecasting example”)
parser.add_argument("--train-window", default=2160, type=int)
parser.add_argument("--test-window", default=336, type=int)
parser.add_argument("--stride", default=168, type=int)
parser.add_argument("-n", "--num-steps", default=501, type=int)
parser.add_argument("-lr", "--learning-rate", default=0.05, type=float)
parser.add_argument("--dct", action="store_true")
parser.add_argument("--num-samples", default=100, type=int)
parser.add_argument("--log-every", default=50, type=int)
parser.add_argument("--seed", default=1234567890, type=int)
args = parser.parse_args()
main(args)
I was trying to run this program in Jupyter notebook, but it will get errors such as
usage: ipykernel_launcher.py [-h] [--train-window TRAIN_WINDOW]
[--test-window TEST_WINDOW] [--stride STRIDE]
[-n NUM_STEPS] [-lr LEARNING_RATE] [--dct]
[--num-samples NUM_SAMPLES]
[--log-every LOG_EVERY] [--seed SEED]
ipykernel_launcher.py: error: unrecognized arguments: -f C:\Users\AppData\Roaming\jupyter\runtime\kernel-4c744f03-3278-4aaf-af5e-50c96e9e41cd.json
An exception has occurred, use %tb to see the full traceback.
SystemExit: 2
my question is that, what are the right approaches or the modifications I need to make if I want to run a python program, which setup input parameters using argparse type of mechanism, in Jupyter Notebook?
Your code should be indented differently so you can import it into your notebook, or into another Python script. The whole point of the if __name__ == "__main__": block is that it gets executed immediately when Python parses the file; the condition is true only when you run the file directly, not when you import it. But the block needs to be indented differently, so that it's not inside any def or class or other block structure.
The way to use this from a notebook, then, is to call main (or whichever other functions from the imported code you want to run) with your desired parameters.
In this case, main has been designed to expect an Argparse object as its argument, which is quite unfortunate. A better design would simply do the argument parsing inside main, and expose a different function or set of functions for reuse as a library.
Assuming your main function's internals look something like
def main(args):
print(
real_main(args.train_window, args.test_window,
stride=args.stride, num_steps=args.num_steps,
learning_rate=args.learning_rate,
dct=args.dct, num_samples=args.num_samples,
log_every=args.log_every, seed=args.seed))
and supposing you wanted to run the equivalent of
python thatfile.py -n 23 -lr 0.7--dct --num-samples 2300
the equivalent code in your notebook would look like
from thatfile import real_main as that_main
print(that_main(2160, 336, num_steps=23,
learning_rate=0.7, dct=True,
num_samples=2300))
where the first two values are simply copied from the argparse defaults, and I obviously had to speculate a great deal about which parameters are required and which are optional keyword parameters, and whether they are named identically to the argparse field names.
I am completely new to Python, just started today and getting to grips with Python. Running it in Visual Studio btw.
Came across the import argParse and this is where things got a bit confusing for me.
I have some code I'm trying to get to work but it won't and I am quite clueless.
I'm getting an error on the code args = parser.parse_args() and I have no idea why either. Code is below
import math
import argparse
parser = argparse.ArgumentParser(description='calculate')
parser.add_argument('radius', type=int, help="radius plzz")
parser.add_argument('height', type=int, help="height plzz")
args = parser.parse_args()
def cylinder_volume(radius, height):
vol = (math.pi) * (radius ** 2) * height
return vol
if __name__ == '__main__':
print(cylinder_volume(args.radius, args.height))
I do have an idea of what's going on in this code but I don't know why it won't run as expected?
Maybe because I'm using Visual Studio? Maybe I need to import something else..
I have an image of the error!
args = parser.parse_args() parses the command line arguments (accessible as the sys.argv list) and makes the first argument args.radius and the second argument args.height, per the calls to the add_argument method. So all you need to do is to run the script from the command line with two integer arguments, e.g.:
script_name.py 123 456
or to test it in an IDE such as Visual Studio, you can pass a list of arguments to parse_args instead:
args = parser.parse_args(['123', '456'])
which outputs:
21673294.79680895
you can add 'dest=(str)' to send the argument as an attribute of args.
parser.add_argument(
'radius',
type=int,
help="radius plzz",
dest='radius'
)
parser.add_argument(
'height',
type=int,
help="height plzz",
dest='height'
)
Then you can call the arguments as you did in:
print(cylinder_volume(args.radius, args.height))
I'm trying to create a command line interface for the dft.ba URL shortener using python's argparse and a function in .profile which calls my python script. This is the business end of the code in my python script:
parser = argparse.ArgumentParser(description='Shortens URLs with dft.ba')
parser.add_argument('LongURL',help='Custom string at the end of the shortened URL')
parser.add_argument('--source','-s',help='Custom string at the end of the shortened URL')
parser.add_argument('-c','--copy', action="store_true", default=False, help='Copy the shortened URL to the clipboard')
parser.add_argument('-q','--quiet', action="store_true", default=False, help="Execute without printing")
args = parser.parse_args()
target_url=args.LongURL
source=args.source
print source
query_params={'auth':'ip','target':target_url,'format':'json','src':source}
shorten='http://dft.ba/api/shorten'
response=requests.get(shorten,params=query_params)
data=json.loads(response.content)
shortened_url=data['response']['URL']
print data
print args.quiet
print args.copy
if data['error']:
print 'Error:',data['errorinfo']['extended']
elif not args.copy:
if args.quiet:
print "Error: Can't execute quietly without copy flag"
print 'Link:',shortened_url
else:
if not args.quiet:
print 'Link:',shortened_url
print 'Link copied to clipboard'
setClipboardData(shortened_url)
and then in .profile I have this:
dftba(){
cd ~/documents/scripts
python dftba.py "$1"
}
running dftba SomeURL will spit a shortened URL back at me, but none of the options work.When I try to use -s SomeSource before the LongURL, it gives error: argument --source/-s: expected one argument, when used afterwards it does nothing and when omitted gives error: too few arguments. -c and -q give error: too few arguments for some reason. The copy to clipboard function I'm using works perfectly fine if I force copying, however.
I'm very much feeling my way through this, so I'm sorry if I've made some glaringly obvious mistake. I get the feeling the problem's in my bash script, I just don't know where.
Any help would be greatly appreciated. Thank you.
Lets just focus on what the parser does
parser = argparse.ArgumentParser(description='Shortens URLs with dft.ba')
parser.add_argument('LongURL',help='Custom string at the end of the shortened URL')
parser.add_argument('--source','-s',help='Custom string at the end of the shortened URL')
parser.add_argument('-c','--copy', action="store_true", default=False, help='Copy the shortened URL to the clipboard')
parser.add_argument('-q','--quiet', action="store_true", default=False, help="Execute without printing")
args = parser.parse_args()
print args # add to debug the `argparse` behavior
LongURL is a positional argument that is always required. If missing you'll get the 'too few arguments' error message.
source is optional, but when provided must include an argument. If not given args.source is None. As written the source argument must be given in ADDITION to the LongURL one.
Both args.copy and args.quiet are booleans; default value is False; and True if given. (the default=False parameter is not needed.)
I haven't tried to work through the logic using copy and quiet. That won't come into play if there are problems earlier with LongURL and source.
Compare these samples:
In [38]: parser.parse_args('one'.split())
Out[38]: Namespace(LongURL='one', copy=False, quiet=False, source=None)
In [41]: parser.parse_args('-s one two -c -q'.split())
Out[41]: Namespace(LongURL='two', copy=True, quiet=True, source='one')
It may also help to look at what parse_args is parsing: sys.argv[1:] (if you have doubts about what you are getting from .profile).
I am trying to make a Python program that uses the argparse module to parse command-line options.
I want to make an optional argument that can either be named or positional. For example, I want myScript --username=batman to do the same thing as myScript batman. I also want myScript without a username to be valid. Is this possible? If so, how can it be done?
I tried various things similar to the code below without any success.
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument("-u", "--user-name", default="admin")
group.add_argument("user-name", default="admin")
args = parser.parse_args()
EDIT: The above code throws an exception saying ValueError: mutually exclusive arguments must be optional.
I am using Python 2.7.2 on OS X 10.8.4.
EDIT: I tried Gabriel Jacobsohn's suggestion but I couldn't get it working correctly in all cases.
I tried this:
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument("-u", "--user-name", default="admin", nargs="?")
group.add_argument("user_name", default="admin", nargs="?")
args = parser.parse_args()
print(args)
and running myScript batman would print Namespace(user_name='batman'), but myScript -u batman and myScript --user-name=batman would print Namespace(user_name='admin').
I tried changing the name user-name to user_name in the 1st add_argument line and that sometimes resulted in both batman and admin in the namespace or an error, depending on how I ran the program.
I tried changing the name user_name to user-name in the 2nd add_argument line but that would print either Namespace(user-name='batman', user_name='admin') or Namespace(user-name='admin', user_name='batman'), depending on how I ran the program.
The way the ArgumentParser works, it always checks for any trailing positional arguments after it has parsed the optional arguments. So if you have a positional argument with the same name as an optional argument, and it doesn't appear anywhere on the command line, it's guaranteed to override the optional argument (either with its default value or None).
Frankly this seems like a bug to me, at least when used in a mutually exclusive group, since if you had specified the parameter explicitly it would have been an error.
That said, my suggested solution, is to give the positional argument a different name.
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument('-u','--username')
group.add_argument('static_username',nargs='?',default='admin')
Then when parsing, you use the optional username if present, otherwise fallback to the positional static_username.
results = parser.parse_args()
username = results.username or results.static_username
I realise this isn't a particularly neat solution, but I don't think any of the answers will be.
Here is a solution that I think does everything you want:
import argparse
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("-u", "--user-name", default="admin")
# Gather all extra args into a list named "args.extra"
parser.add_argument("extra", nargs='*')
args = parser.parse_args()
# Set args.user_name to first extra arg if it is not given and len(args.extra) > 0
if args.user_name == parser.get_default("user_name") and args.extra:
args.user_name = args.extra.pop(0)
print args
If you run myScript -u batman or myScript --user-name=batman, args.user_name is set to 'batman'. If you do myScript batman, args.user_name is again set to 'batman'. And finally, if you just do myScript, args.user_name is set to 'admin'.
Also, as an added bonus, you now have all of the extra arguments that were passed to the script stored in args.extra. Hope this helps.
Try to use the "nargs" parameter of the add_argument method.
This way it works for me.
Now you can add the username twice,
so you have to check it and raise an error, if you want.
import argparse
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("-u", "--user-name", default="admin")
parser.add_argument("user_name", default="admin", nargs="?")
args = parser.parse_args()
print(args)
I have the following code at the minute:
parser = argparse.ArgumentParser(prog='Tempus')
ex_group = parser.add_mutually_exclusive_group(required=True)
## Miscellaneous but needed args
parser.add_argument('--mode', type=str, choices=['xml', 'text', 'term'],
dest='mode', required=True, help='export mode')
parser.add_argument('-v', '--verbose', action='store_true',
dest='verbose', help='enable verbose/debug mode')
# Input methods
ex_group.add_argument('--i', action='store_true',
dest='interactive', help='enter interactive mode')
ex_group.add_argument('--p', metavar='I', type=float,
dest='integer', help='percentage to use')
args = parser.parse_args()
However when I pass the arguments that are needed, in any order, I get the error:
Tempus: error: argument --mode is required
And this happens, even when I pass that argument. Any way to sort this?
Thank you!
EDIT: Thanks everyone, I got it working, turns out executing it without first specifying the python exe before it doesn't pass arguments.
Just another quick question: is it possible to create an argument similar to --mode in my code, but let an additional argument be passed to one of the choices?
For example, have a command such as --input which can take two arguments 'integer' and 'interactive', but I can also pass a number to the --input integer command? So the command would read: --input integer 23 for example? Is this possible?
Try
1. to print sys.argv before parsing or
2. to explicitely add arguments inside the script as in http://docs.python.org/dev/library/argparse.html#parsing-arguments
So you can exclude any confusion about which arguments argparse actually sees.