Using sys.argv to retrieve different functions - python

So let's say I have these lines of code:
if __name__ == '__main__':
if '-h' in sys.argv:
show_help()
elif '-f' or 'function'in sys.argv:
print(function1)
elif '-n'or '-name' in sys.argv:
print(function2)
elif '-e' or '-extension'in sys.argv:
print(function3])
elif '-m' or '-missing'in sys.argv:
print(function4)
elif 'r' or '-range' in sys.argv:
print(function5)
else:
exit
The letters are supposed to be inputs from the user in the bash terminal.
Showing the help method works and it is able to show all of the strings.
The -f input works and shows the contents that I need in that function, however the code just spits out the content from function 1 and not from function2 and so on.
How do I get these different letters, -f, -n, -e, -m (if inputted) to carry out that function and spit out that information?
Also is there a more efficient way to do this without using argparse for a beginner Python scripter?

To test if any one of two values is in a list, you can't use the or operator with the in operator. You need to test each value separately using the in operator, like this:
if '-h' in sys.argv:
show_help()
elif '-f' in sys.argv or '-function' in sys.argv:
print(function1)
elif '-n' in sys.argv or '-name' in sys.argv:
print(function2)
elif '-e' in sys.argv or '-extension'in sys.argv:
print(function3])
elif '-m' in sys.argv or '-missing'in sys.argv:
print(function4)
elif '-r' in sys.argv or '-range' in sys.argv:
print(function5)
else:
exit

I highly suggest using argparse.
If you prefer not to, creating a dictionary of flags is also possible:
flags = {
'-h': show_help,
'-f': function1,
'-function': function1,
'-n': function2,
'-name': function2,
'-e': function3,
'-extension': function3,
'-m': function4,
'-missing': function4,
'-r': function5,
'-range': function5,
}
if __name__ == '__main__':
for flag in sys.argv:
print(flags[flag])
By creating a dictionary, you're able to just look up the keys.
It results in cleaner, faster, and more maintainable code.

Related

How to execute python script which expects command line args by bash script?

I have oracle's wlst.sh bash script that invokes a python script. This python script expects command line arguments.
/somewhere/oracle/Middleware/wlsserver_10.3/common/bin/wlst.sh /path/foo.py -a aaa -b bbb
I realized that it only executes wlst.sh but not the foo.py if I pass the command line arguments. If I don't pass command line args then foo.py is executed. I tried to wrap entire python script calling with double-quote that didn't do a trick. What would be correct syntax I can use?
Update:
wlst.sh is the given script from oracle suite. Here is foo.py. I don't do anything with passed in parameters for now. If I keep connectToAdmin() only without passing any parameters then print "Successfully connected" is printed however if I include main(sys.argv) method then foo.py is never executed.
import sys, getopt
def usage():
print "usage: foo.py -a aaa -b bbb"
sys.exit(2)
def connectToAdmin():
try:
connect(<username>,<passwd>,"t3://fooServer:<port>")
print "Successfully connected"
except WLSTException, we:
print "Unable to connect to administration server.."
sys.exit(2)
# Parse command line arguments
def main(argv):
unixOptions = "ha:b:"
gnuOptions = ["help","bar","boo"]
boo = ""
bar = ""
try:
opts, args = getopt.getopt(argv[1:], unixOptions, gnuOptions)
except getopt.GetoptError, err:
print str(err)
usage()
for o, a in opts:
if o in ("-h", "--help"):
usage()
elif o in ("-a", "--bar"):
boo = a
elif o in ("-b", "--boo"):
bar = a
connectToAdmin()
if __name__ == "__main__":
main(sys.argv)

Make my python command line program interactive with argparse

i'm trying to make my python program interactive in command line, user should be able to do stuff like :
python myprogram.py --create
then
python myprogram.py --send
The problem in this when is that the program stop and restart each time so i lose my variable and object that i created with the first command.
I'm using argparse on this way:
parser = argparse.ArgumentParser()
parser.add_argument('-c','--create' ,help='',action='store_true')
parser.add_argument('-s','--send',help='',action='store_true')
args = parser.parse_args()
if args.create:
create()
elif args.send :
send()
I don't want to stop the program between the command, how to do this ?
example : https://coderwall.com/p/w78iva
Here's a simple interactive script. I use argparse to parse the input lines, but otherwise it is not essential to the action. Still it can be an handy way of adding options to your 'create' command. For example, ipython uses argparse to handle its %magic commands:
import argparse
parser = argparse.ArgumentParser(prog='PROG', description='description')
parser.add_argument('cmd', choices=['create','delete','help','quit'])
while True:
astr = raw_input('$: ')
# print astr
try:
args = parser.parse_args(astr.split())
except SystemExit:
# trap argparse error message
print 'error'
continue
if args.cmd in ['create', 'delete']:
print 'doing', args.cmd
elif args.cmd == 'help':
parser.print_help()
else:
print 'done'
break
This could be stripped down to the while loop, the raw_input line, and your own evaluation of the astr variable.
The keys to using argparse here are:
parse_args can take a list of strings (the result of split()) instead of using the default sys.argv[1:].
if parse_args sees a problem (or '-h') it prints a message and tries to 'exit'. If you want to continue, you need to trap that error, hence the try block.
the output of parse_args is a simple namespace object. You access the arguments as attributes.
you could easily substitute your own parser.
The diffrence in cmd and argparse is that cmd is a "line-oriented command interpreter" while argparse is a parser for sys.argv.
Your example parses sys.argv that you pass while running your program and then if it gets the value you start a function and then quits.
argparse will only parse the sys.argv while running the program.
You could add some code to be able to work with the args you pass like a function or class or make in program menu that you could operate with raw_input.
Example:
class Main():
def __init__(self, create=None, send=None):
if create:
self.create(create)
elif send:
self.send(send)
option = raw_input('What do you want to do now?')
print option
def create(self, val):
print val
def send(self, val):
print val
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('-c','--create' ,help='',action='store_true')
parser.add_argument('-s','--send',help='',action='store_true')
args = parser.parse_args()
Main(args.create, args.send)
Other then that Python argparse and controlling/overriding the exit status code or python argparse - add action to subparser with no arguments? might help.
In the first it shows how you can override the quit and in the second how can you add subcommands or quitactions.

calling functions from command prompt

Here is the extract of the script (untested)
def start_custer():
try:
myidentifier=mydict['DescribeClustersResponse']['DescribeClustersResult']['Clusters'][0]['ClusterIdentifier']
except IndexError:
conn.restore_from_cluster_snapshot('vi-mar5-deliveryreport-new', mysnapidentifier, availability_zone='us-east-1a')
def stop_cluster():
try:
myidentifier=mydict['DescribeClustersResponse']['DescribeClustersResult']['Clusters'][0]['ClusterIdentifier']
conn.delete_cluster(myidentifier, skip_final_cluster_snapshot=False, final_cluster_snapshot_identifier=myvar)
except:
print "error"
Are these functions technically (syntactically) correct?
How do I call them while calling the python script? I need to either start or stop cluster at a time, not both.
For your second question, I'd parse the command line via argparse:
import argparse
parser = argparse.ArgumentParser(description="Manage the cluster")
parser.add_argument("action", choices=["stop", "start"],
help="Action to perform")
args = parser.parse_args()
if args.action == "start":
start_cluster()
if args.action == "stop":
stop_cluster()
Others have shown you the best way to do this, but for the record, you can also do this from the command line:
python -c "import cluster; cluster.start_cluster()"
(assuming your module file is named cluster.py -- adjust the import statement accordingly if not)
This isn't as user-friendly as parsing the command line yourself but it'll do in a pinch.
1) It's Syntactically correct, if you have defined conn somewhere and imported it !
2)
def stop_cluster():
## Your code
def fun():
## your code
if __name__ == "__main__":
import sys
globals()[sys.argv[1]]()
Usage:
python2.7 test_syn.py fun
I have added a main function to your script which checks for command line args, then prompts you if no valid argument has been supplied:
import sys
def start_custer():
try:
myidentifier=mydict['DescribeClustersResponse']['DescribeClustersResult']['Clusters'][0]['ClusterIdentifier']
except IndexError:
conn.restore_from_cluster_snapshot('vi-mar5-deliveryreport-new', mysnapidentifier, availability_zone='us-east-1a')
def stop_cluster():
try:
myidentifier=mydict['DescribeClustersResponse']['DescribeClustersResult']['Clusters'][0]['ClusterIdentifier']
conn.delete_cluster(myidentifier, skip_final_cluster_snapshot=False, final_cluster_snapshot_identifier=myvar)
except:
print "error"
def main():
valid_args, proc = ['start','stop'], None
# check if cmd line args were passed in (>1 as sys.argv[0] is name of program)
if len(sys.argv) > 1:
if sys.argv[1].lower() in valid_args:
proc = sys.argv[1].lower()
# if a valid arg was passed in this has been stored in proc, if not prompt user
while not proc or proc not in valid_args:
print "\nPlease state which procedure you want to call, valid options are:", valid_args
proc = raw_input('>>> ').lower()
# prompt user if invalid
if proc not in valid_args:
print proc, 'is not a valid selection.'
if proc == 'start':
start_custer()
elif proc == 'stop':
stop_cluster()
# this makes the script automatically call main when starting up
if __name__ == '__main__':
main()
You can call this from the command line e.g. if you were in the same directory as the file (e.g. named cluster_ctrl.py) just:
python cluster_ctrl.py start

Python Daemon calling a subprocess periodically

I am building a simple pyhon daemon based on Sander Marechal's code. Daemon's whole purpose is to run a php file every second (php file loops through database checking values and updating database). Problem arises on the section
subprocess.call(['php','test.php'])
I can run "php test.php" on shell and it does what it is suppose to do but when it is called periodically from the daemon it doesn't seem to be executed. I also know daemon works on the background via checking running process ps aux | grep "daemon-example" also i included a do_something function which records every time function executed and appends time to a text file.
#!/usr/bin/env python
import sys, time,subprocess
from daemon import Daemon
def runphp():
#subprocess.call(['php ~/pydaemon/test.php'], shell=True)
subprocess.call(['python', 'test.py'])
def do_something():
with open("/tmp/current_time.txt",'a') as f:
f.write("The time is now\n" + time.ctime())
class MyDaemon(Daemon):
def run(self):
while True:
time.sleep(1)
do_something()
subprocess.call(['php','test.php'])
#runphp()
if __name__ == "__main__":
daemon = MyDaemon('/tmp/daemon-example.pid')
if len(sys.argv) == 2:
if 'start' == sys.argv[1]:
daemon.start()
elif 'stop' == sys.argv[1]:
daemon.stop()
elif 'restart' == sys.argv[1]:
daemon.restart()
else:
print "Unknown command"
sys.exit(2)
sys.exit(0)
else:
print "usage: %s start|stop|restart" % sys.argv[0]
sys.exit(2)
The script you are trying to run is not executed because the working directory is the root directory ('/') and that's because of this piece of code:
# decouple from parent environment
os.chdir("/")
So actually your code tries to execute: python /test.py(which does not exist) and not 'your_current_directory/test.py'.
To fix it either remove os.chdir("/"), or provide the full path to the file like so:
subprocess.call(['python','my_full_path_to_working_directory/test.py'])

ArgumentParser -h (help) will not work

I cannot get ArgumentParser to work. What's wrong with the following:
import argparse
parser=argparse.ArgumentParser(description='''I wish this description would output''',
epilog='''Please out the epilog''')
parser.add_argument('-l', type=str, default='info', help='logging level. Default is info. Use debug if you have problems.')
args=parser.parse_args()
def main():
print("goodbye")
if __name__ == "__main__":
#main
main()
When I run myscript -h I see no help.
I am running Python 2.7 on Windows 7. I have Python on my path and also pathext set as:
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.py
The argsparse code never actually gets executed. By executing the script from the command line, you're calling main(), which simply prints and exits. You have to call parse_args() in the main() function for this to work.
import argparse
# Personally, I think these belong in the main()
# function as well, but they don't need to be.
parser = argparse.ArgumentParser(
description="I wish this description would output",
epilog="Please out the epilog"
)
parser.add_argument(
"-l",
type=str,
default="info",
help="logging level. Default is info. Use debug if you have problems."
)
def main():
args = parser.parse_args() # Parses arguments
print("goodbye")
if __name__ == "__main__":
main() # Calls main
Produces:
~/Desktop $ python untitled.py --help
usage: untitled.py [-h] [-l L]
I wish this description would output
optional arguments:
-h, --help show this help message and exit
-l L logging level. Default is info. Use debug if you have problems.
Please out the epilog
jcollado claims your code worked fine on Ubuntu--I find this very curious.
If you run this script from the command line you're going to just print 'goodbye', put the argparse code after if __name__ == "__main__":.
OK weird answer for this. The problem was resolved by calling the program as:
python myscript.py -h
If you add python to your path, set file associations and then just do:
myscript.py -h
it will not pick up the -h

Categories