Argparse with multiple subparsers in one command - python

I want to be able to achieve something like this:
'python program host add 192.168.1.1'
'python program host remove 192.168.1.1'
I don't know how to properly code 'add' or 'remove' subparser.
import argparse
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
host_cmd = subparsers.add_parser('host')
host_cmd.set_defaults(func=host)
add_cmd.add_argument('add', dest='add')
I want to be able to read the variable that the user pass in (in this case, 192.168.1.1).

With current code you can create only host --add 192.168.1.1 but it is much simpler code.
import argparse
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='parser')
host_cmd = subparsers.add_parser('host')
host_cmd.add_argument('--add')
host_cmd.add_argument('--remove')
args = parser.parse_args()
print(args)
if args.parser == 'host':
if args.add is not None:
print('add host:', args.add)
if args.remove is not None:
print('remove host:', args.remove)
You need subparser in subparser - host add 192.168.1.1
import argparse
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='parser')
host_cmd = subparsers.add_parser('host')
host_subparsers = host_cmd.add_subparsers(dest='parser_host')
host_add_cmd = host_subparsers.add_parser('add')
host_add_cmd.add_argument('ip')
host_remove_cmd = host_subparsers.add_parser('remove')
host_remove_cmd.add_argument('ip')
args = parser.parse_args()
print(args)
if args.parser == 'host':
if args.parser_host == 'add':
print('add host:', args.ip)
elif args.parser_host == 'remove':
print('remove host:', args.ip)
EDIT: example for host add port 80 but there is conflict with host add 192.168.1.1 so I removed it
import argparse
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='parser')
host_cmd = subparsers.add_parser('host')
host_subparsers = host_cmd.add_subparsers(dest='parser_host')
host_add_cmd = host_subparsers.add_parser('add')
#host_add_cmd.add_argument('ip')
add_subparsers = host_add_cmd.add_subparsers(dest='parser_add')
host_add_port_cmd = add_subparsers.add_parser('port')
host_add_port_cmd.add_argument('add_port')
host_remove_cmd = host_subparsers.add_parser('remove')
host_remove_cmd.add_argument('ip')
args = parser.parse_args()
print(args)
if args.parser == 'host':
if args.parser_host == 'add':
if args.parser_add == 'port':
print('add port', args.add_port)
elif args.parser_host == 'remove':
print('remove', args.ip)

Related

python command line arguments, how to pass argument as value for script

I am having a hard time passing the arguments as value for my script in python. Here's my code:
import request, json, sys
def main():
url = 'https://jsonplaceholder.typicode.com/posts'
r = requests.get(url)
data = json.loads(r.text)
if len(sys.argv) != 3:
print("Usage must equal [userId] [postId]")
exit()
for user in data:
if user['userId'] == sys.argv[1] and user['id'] == sys.argv[2]:
print('here i am')
print(user)
if __name__ == "__main__":
main()
When I run python -m test 1 1, nothing happens. But it does trigger when I don't have enough arguments or too many.
The problem is that command line arguments are strings and the data you seek are integers. You could convert arg[1] and arg[2] to integers or you could use the argparse module to build a more comprehensive command line parser.
import requests, json, sys, argparse
def main():
parser = argparse.ArgumentParser(description='Do all the things')
parser.add_argument('user_id', type=int,
help='the user id')
parser.add_argument('id', type=int,
help='the other id')
args = parser.parse_args()
url = 'https://jsonplaceholder.typicode.com/posts'
r = requests.get(url)
data = json.loads(r.text)
for user in data:
if user['userId'] == args.user_id and user['id'] == args.id:
print('here i am')
print(user)
if __name__ == "__main__":
main()

arg is not defined , argv makes one list. whats wrong?

I'm new to python and scapy. I'm trying to make a DHCP-starvation script. Only my arguments are not working. I get a NameError: name 'arg' is not defined error. When I change arg to argv i only get one list. What am I doing wrong?
#!/usr/bin/python3
from scapy.all import *
import sys
import time
import getopt
def main(argv):
conf.checkIPaddr = False
brmac = 'ff:ff:ff:ff:ff:ff'
network = ""
serverid = ""
begin = 1
end = 1
try:
opts, args = getopt.getopt(argv,"hnsb:e:")
except getopt.GetoptError:
print("dhcp.py -n 192.168.1. -s 192.168.1.1 -b 20 -e 250")
sys.exit(2)
for opt, args in opts:
if opt == "-h":
print("dhcp.py -n 192.168.1. -s 192.168.1.1 -b 20 -e 250")
sys.exit()
elif opt in ("-n"):
network = arg
elif opt in("-s"):
serverid = arg
elif opt in ("-b"):
begin = arg
elif opt in("e"):
end = arg
for ip in range(int(begin), int(end)):
adr = RandMAC()
sendp(Ether(src=adr, dst=brmac)/IP(src='0.0.0.0', dst='255.255.255.255')/UDP(sport=68, dport=67)/BOOTP(chaddr=adr)/DHCP(options=[('message-type', 'request'),("server_id",str(serverid)), ("requested_addr",str(network) + str(ip)), 'end']))
print("requesting ip " + str(network) + str(ip))
time.sleep(2)
if __name__ == "__main__":
main(sys.argv[1:])
You're using for opt, args in opts: as for loop, but then inside that for loop you're trying to refer to args as arg which does not exist.
Possible solutions to solve your error:
Change arg inside the for loop to args, so it matches the variable in the for loop
Change the variable name args to arg, so it matches the variable in your code

argparse subparsers with functions

Hello I am starting with argparse. My goal is to build a CLI with main commands that accept arguments and redirect to the corresponding commands functions. Here is what I did so far:
def main():
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
command1_parser = subparsers.add_parser('command1')
command1_parser.set_defaults(func=command1)
command1_parser.add_argument('--name', dest='name')
command2_parser = subparsers.add_parser('command2')
command2_parser.set_defaults(func=command2)
command2_parser.add_argument('--frequency', dest='frequency')
args = parser.parse_args()
def command1():
# do something with args.name
def command2():
# do something with args.frequency
if __name__ == '__main__':
main()
When I do:
entrypoint command1 --name Hello
Or:
entrypoint command2 --frequency 10
It fails to catch the corresponding args. What I am doing wrong? Thanks!
Because you need to invoke the function manually by args.func(args):
import argparse
def main():
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
command1_parser = subparsers.add_parser('command1')
command1_parser.set_defaults(func=command1)
command1_parser.add_argument('--name', dest='name')
command2_parser = subparsers.add_parser('command2')
command2_parser.set_defaults(func=command2)
command2_parser.add_argument('--frequency', dest='frequency')
args = parser.parse_args()
args.func(args)
def command1(args):
print("command1: %s" % args.name)
def command2(args):
print("comamnd2: %s" % args.frequency)
if __name__ == '__main__':
main()

Checking command-lines parameters with usage.Options

I am parsing and checking command-lines parameters with usage.Options.
#!/usr/bin/python
from twisted.python import usage
import sys
class Options(usage.Options):
"""
Defines the default input parameters
"""
optParameters = [
["param", "p", 1, "Int Parameter", int],
]
if __name__ == "__main__":
options = Options()
try:
options.parseOptions()
except Exception, e:
print '%s: %s' % (sys.argv[0], e)
print '%s: Try --help for usage details.' % (sys.argv[0])
sys.exit(1)
else:
if options['param'] < 0 or options['param'] > 10:
print "param out of the range [0,10]"
sys.exit(1)
I don't know how to check that value of thi input param is a number. If a user accidentally inserts a letter he gets this:
Parameter type enforcement failed: invalid literal for int() with base
10: 'd'
Why don't use optparse?
from optparse import OptionParser
options, args = parser.parse_args()
def args():
parser = OptionParser(usage='usage: %prog [options]', version='%prog 1.0.0')
parser.add_option(.....)
return parser
Update:
You can have something like this. Add and replace everything you want:
class Main:
def __init__(self):
parser = self.get_arg()
self.set_arg(parser)
def set_arg(self, parser):
options, args = parser.parse_args()
if len(sys.argv) == 1:
print 'Error: Usage: python %s <options>' % sys.argv[0]
sys.exit()
input_file = options.input_file
flag = options.flag
def get_arg(self):
parser = OptionParser(usage='usage: %prog [options]', version='%prog 1.1.0')
parser.add_option('-i', '--input-file', action='store', type='string', dest='input_file', default=None,
help='Input file.')
parser.add_option('-f', '--flag', action='store_true', dest='flag', default=False,
help='A flag in your app')
return parser
if __name__ == '__main__':
Main()

Python list with Vcenter vm

I found a Python script to list all Vcenter VM attributes, but now I need to register some of attributes into a Python list (or array, dict... ).
But it doesn't works.
My getVminfos.py :
EDIT : the right file :
import argparse
import atexit
import itertools
import unicodedata
import pyVmomi
from pyVmomi import vmodl
from pyVmomi import vim
from pyVim.connect import SmartConnect, Disconnect
def GetArgs():
parser = argparse.ArgumentParser(description='Process args for retrieving all the Virtual Machines')
parser.add_argument('-s', '--host', required=True, action='store',help='Remote host to connect to')
parser.add_argument('-o', '--port', type=int, default=443, action='store',help='Port to connect on')
parser.add_argument('-u', '--user', required=True, action='store',help='User name to use when connecting to host')
parser.add_argument('-p', '--password', required=False, action='store',help='Password to use when connecting to host')
args = parser.parse_args()
return args
def print_vm_info(virtual_machine):
"""
Print information for a particular virtual machine or recurse into a
folder with depth protection
"""
Ansible_Hosts = []
Ansible_Groups = []
Ansible_Names = []
summary = virtual_machine.summary
print("Name : ", summary.config.name)
print("Template : ", summary.config.template)
#print("Path : ", summary.config.vmPathName)
print"Guest : ", str(unicodedata.normalize('NFKD', summary.config.guestFullName))
#print("Instance UUID : ", summary.config.instanceUuid)
#print("Bios UUID : ", summary.config.uuid)
print"State : ", summary.runtime.powerState
if summary.guest is not None:
ip_address = summary.guest.ipAddress
if ip_address:
Ansible_Hosts.append([ip_address])
print "Ansible_Hosts[1:15]", Ansible_Hosts[1:15]
def main():
args = GetArgs()
try:
si = SmartConnect(host=args.host,user=args.user,pwd=args.password,port=int(args.port))
if not si:
print("Could not connect to the specified host using specified "
"username and password")
return -1
atexit.register(Disconnect, si)
content = si.RetrieveContent() # get root folder
container = content.rootFolder # starting point to look into
viewType = [vim.VirtualMachine] # object types to look for
recursive = True # whether we should look into it recursively
containerView = content.viewManager.CreateContainerView(
container, viewType, recursive)
children = containerView.view
for child in children:
print_vm_info(child)
except vmodl.MethodFault as error:
print("Caught vmodl fault : " + error.msg)
return -1
return 0
# Start program
if __name__ == "__main__":
main()
Prints works like a charm, but always my lists (Ansible_Hosts, ...) are empty...
The lists initialization statements (Ansible_Hosts = [] etc.) should go to main()

Categories

Resources