I have a Python 3 program that uses the argparse module to collect command line arguments, and I would like to add a feature to my program so that arguments may be taken which set an arbitrary internal variable to a value at runtime.
For example: ./program.py --regular-option +myvar=apples +othervar=oranges
Is this something that argparse can handle? Otherwise, how do I prevent argparse from thinking a nonexistent option has been passed while I manually extract these options from sys.argv?
Related
I have a script list nearly 100 scripts to which I need to pass argument for each scripts and these arguments are different for each script.
The way I tried passing arguments for each script individually which is consuming a lot of time and manuval intervention. Can any one suggest me an easiest way to pass my inputs to these scripts.
code i have tried the below code for passing same values for all input boxes:
driver.find_element(By.XPATH,
'//[#id="side-maincontainer-wrapper"]/div/div/div[2]/earms-suitehome/div/div/div/div/div[2]/div[2]/div1/earms-categorydetails/div/div/div[3]/div[2]/clr-datagrid/clr-dg-action-bar/button[3]').click()
num_scripts=54
for i in range(0, (num_scripts - 1)):
#time.sleep(20)
driver.find_element(By.XPATH,
'//[#id="side-maincontainer-wrapper"]/div/div/div[2]/earms-requestrunhome/earms-testbedselection/div/div/div/div/div[2]/div/div1/div/form/div/div/div/div/div/div/clr-datagrid/div/div/div/clr-dg-table-wrapper/div[2]/clr-dg-row1/div/clr-dg-cell[3]/input//div').send_keys(
"--crft --crft-devices pireg-nyquist1-1 pireg-nyquist1-2 --btrace-devices uut --btrace --configuration /auto/arf1/vramiyen/pyats_crft/SELinux_plugin/config.yaml --selinux --selinux-devices uut --template /auto/bgl-xeinfra/pmotukan/template.input --platform /auto/arf1/vramiyen/pyats_crft/SELinux_plugin/platform.py")
image snippet
attached the picture below ,so i need to pass my args in that cmd line input box,and the arguments for each box are different
I have used this module before for parsing arguments:
https://docs.python.org/3/library/argparse.html
The argparse module makes it easy to write user-friendly command-line interfaces. The program defines what arguments it requires, and argparse will figure out how to parse those out of sys.argv. The argparse module also automatically generates help and usage messages and issues errors when users give the program invalid arguments.
This is just a general solution as the question currently contains no code.
I have a Python script that will later call multiple Bash scripts with supprocess.run. When calling the Python script, the user should be able to specify lists of arguments (some of which might start with hyphens) for the Bash scripts like
python script.py \
--bash-args1 --param1 val1 --param2 val2 \
--bash-args2 bla --param3 val3 --blu
Argparse should parse this into Namespace(bash_args1=['--param1', 'val1', '--param2', 'val2'], bash_args2=['bla', '--param3', 'val3', '--blu']). Is there a canonical way of achieving this? I cannot use nargs=argparse.REMAINDER or parser.parse_known_args because I need to collect the arguments for more than one Bash script and a simple nargs='+' will fail if the secondary arguments start with dashes.
I guess I would need one of the following:
Either something similar to REMAINDER that causes argparse to collect all strings up to the next known argument
an option that tells argparse to ignore dashes in unknown arguments when using nargs='+'.
For posterity:
There are a few ways of working around this limitation of argparse. I wrapped one up and published it on PyPI. You can use it just like argparse. The only difference is that there is an extra option you can supply as nargs parameter in add_argument. When this option is used, the parser collects all unknown arguments (regardless of whether they start with a hyphen or not) until the next known argument. For more info check out the repo on github.
A Python script that I want to use (called snakefood) is normally run from the commandline and takes commandline arguments, eg:
sfood /path/to/my/project
The parsing of the commandline arguments happens in a file called gendeps.py using optparse. However, I want to use the snakefood module from another script. Is there a way I can somehow mock the passing of commandline arguments to snakefood or a way of rewriting gendeps.py so that it doesn't depend on optparse anymore?
You can always assign a new list to sys.argv:
import sys
sys.argv = ['programname', '-iq', '-q', directory]
gendeps.gendeps()
optparse uses sys.argv[1:] as input when no explicit arguments have been passed in.
Consider the following script:
import argparse
parser1 = argparse.ArgumentParser()
parser1.add_argument('-a')
args1 = parser1.parse_args()
parser2 = argparse.ArgumentParser()
parser2.add_argument('-b')
args2 = parser2.parse_args()
I have several questions:
Is parse_args a one-time method or is there a way to clear the
arguments before adding new ones? (e.g. something like
args1.clear() or parser1.clear())
The result of this script is unusable. Although this script accepts
the -a argument, it does not accept any value for 'a'. Nor does it
accept any -b argument. Is there some way to make any of the arguments really work?
This is my actual scenario: I have 2 scripts. Both import the same
file which has initialization code (load config files, create
loggers, etc.), lets call it init.py This init.py file also parses
the arguments only because it needs one value from it. The problem
is that I need one of the scripts to accept other arguments as well.
Since init.py does something with one argument, I cannot wait with
parse_args. How can I make it work?
Edit:
Here is the output of my script:
[prompt]# python2.7 myscript.py -a
usage: a.py [-h] [-a A]
myscript.py: error: argument -a: expected one argument
[prompt]# python2.7 myscript.py -a 1
Namespace(a='1')
usage: a.py [-h] [-b B]
myscript.py: error: unrecognized arguments: -a 1
Your scenario is quite unclear, but I guess what you're looking for is parse_known_args
Here I guessed that you called init.py from the other files, say caller1.py and caller2.py
Also suppose that init.py only parses -a argument, while the original script will parse the rest.
You can do something like this:
in init.py put this in do_things method:
parser = argparse.ArgumentParser()
parser.add_argument('-a')
parsed = parser.parse_known_args(sys.argv)
print 'From init.py: %s' % parsed['a']
In caller1.py:
init.do_things(sys.argv)
parser = argparse.ArgumentParser()
parser.add_argument('-b')
parsed = parser.parse_known_args(sys.argv)
print 'From caller1.py: %s' % parsed['b']
If you call caller1.py as follows: python caller1.py -a foo -b bar, the result will be:
From init.py: foo
From caller1.py: bar
But if your scenario is not actually like this, I would suggest to use #Michael0x2a answer, which is just to use single ArgumentParser object in caller1.py and pass the value appropriately for init.py
This doesn't really make sense, because for all intents and purposes, the parser object is stateless. There's nothing to clear, since all it does is takes in the console arguments, and returns a Namespace object (a pseudo-dict) without ever modifying anything in the process.
Therefore, you can consider parse_args() to be idempotent. You can repeatedly call it over and over, and the same output will occur. By default, it will read the arguments from sys.argv, which is where the console arguments are stored.
However, note that you can pipe in custom arguments by passing in a list to the parse_args function so that the parser will using something other then sys.argv as input.
I'm not sure what you mean. If you call python myscript.py -a 15, args1 will equal Namespace(a='15'). You can then do args1['a'] to obtain the value of 15. If you want to make the flag act as a toggle, call parser.add_argument('-a', action='store_true'). Here is a list of all available actions.
I would try and confine all the console/interface code into a single module and into a single parser. Basically, remove the code to parse the command line from init.py and the second file into an independent little section. Once you run the parser, which presents a unified interface for everything in your program, pass in the appropriate variables to functions inside init.py. This has the added advantage of keeping the UI separate and more easily interchangeable with the rest of the code.
Is anyone able to tell me how to write a conditional for an argument on a python script? I want it to print "Argument2 Entered" if it is run with a second command line arguments such as:
python script.py argument1 argument2
And print "No second argument" if it is run without command line arguments, like this:
python script.py argument1
Is this possible?
import sys
if len(sys.argv)==2: # first entry in sys.argv is script itself...
print "No second argument"
elif len(sys.argv)==3:
print "Second argument"
There are many answers to this, depending on what exactly you want to do and how much flexibility you are likely to need.
The simplest solution is to examine the variable sys.argv, which is a list containing all of the command-line arguments. (It also contains the name of the script as the first element.) To do this, simply look at len(sys.argv) and change behaviour based on its value.
However, this is often not flexible enough for what people expect command-line programs to do. For example, if you want a flag (-i, --no-defaults, ...) then it's not obvious how to write one with just sys.argv. Likewise for arguments (--dest-dir="downloads"). There are therefore many modules people have written to simplify this sort of argument parsing.
The built-in solution is argparse, which is powerful and pretty easy-to-use but not particularly concise.
A clever solution is plac, which inspects the signature of the main function to try to deduce what the command-line arguments should be.
There are many ways to do this simple thing in Python. If you are interested to know more than I recommend to read this article. BTW I am giving you one solution below:
import click
'''
Prerequisite: # python -m pip install click
run: python main.py ttt yyy
'''
#click.command(context_settings=dict(ignore_unknown_options=True))
#click.argument("argument1")
#click.argument("argument2")
def main(argument1, argument2):
print(f"argument1={argument1} and argument2={argument2}")
if __name__ == '__main__':
main()
Following block should be self explanatory
$ ./first.py second third 4th 5th
5
$ cat first.py
#!/usr/bin/env python
import sys
print (len(sys.argv))
This is related to many other posts depending upon where you are going with this, so I'll put four here:
What's the best way to grab/parse command line arguments passed to a Python script?
Implementing a "[command] [action] [parameter]" style command-line interfaces?
How can I process command line arguments in Python?
How do I format positional argument help using Python's optparse?
But the direct answer to your question from the Python docs:
sys.argv -
The list of command line arguments passed to a Python script. argv[0] is the script name (it is operating system dependent whether this is a full pathname or not). If the command was executed using the -c command line option to the interpreter, argv[0] is set to the string '-c'. If no script name was passed to the Python interpreter, argv[0] is the empty string.
To loop over the standard input, or the list of files given on the command line, see the fileinput module.