Argparse: differentiating arguments based on regex?

时间:2018-12-27 12:54:21

标签: python argparse

Is it possible to differentiate between arguments based on a regex with argparse?

I would like my script to accept either an IP address or a network address, but need to be able to differentiate between the two because the backend API call requires me to specify which is used. I'd preferably not use an explicit flag to specify which argument is used, instead using a regex, but not sure this is possible?

Example usage:

ip-lookup.py 192.168.1.1

192.168.1.1 should be assigned to an argument named 'ip'

ip-lookup.py 192.168.0.0/16
ip-lookup.py 192.168.0.0 255.255.0.0
ip-lookup.py 192.168.0.0/255.255.0.0

192.168.0.0/16 should be assigned to an argument named 'network'

Code:

parser = argparse.ArgumentParser(description='Lookup an IP address or network in the backend IPAM system.')
parser.add_argument('ip', help='IP host address', type=str, required=False, **regex to match on IP address**)
parser.add_argument('network', help='IP network address', type=str, required=False, **regex to match on IP network**)

args = parser.parse_args()

args.ip         -> should only exist if the user entered an IP address as parameter
args.network    -> should only exist if the user entered an IP network as parameter

2 个答案:

答案 0 :(得分:2)

我将通过定义非位置参数(在定义时位于它们前面的--)来解决这个问题。例如

import argparse
parser = argparse.ArgumentParser()

parser.add_argument('--ip', help='IP host address', type=str, required=False)
parser.add_argument('--network', help='IP network address', type=str, required=False)

args = parser.parse_args()

print(getattr(args, 'ip'))
print(getattr(args, 'network'))

现在,您可以使用test.py --ip 192.168.1.1test.py --network 192.168.0.0/255.255.0.0来调用它。这将分别返回:

192.168.1.1
None

None
192.168.1.1/255.255.0.0

请注意,如果字符串中包含空格,则需要--network '192.168.1.1 255.255.0.0'

答案 1 :(得分:0)

对于感兴趣的任何人,我还研究了argparse的一些替代方法,例如Click,但是由于以这种方式使用参数并不遵循使用位置参数的unix方式,因此它似乎不是内置的。

我确实设法使其正常运行,直接解析了sys.argv。不太优雅,但是可以正常工作:

import sys
import ipaddress

USAGE = """
 Usage:
    \t ip-lookup.py 192.168.1.1
    \t ip-lookup.py 192.168.0.0/16
    \t ip-lookup.py 192.168.0.0 255.255.0.0
    \t ip-lookup.py 192.168.0.0/255.255.0.0    
    """

# Parse command-line arguments
if (len(sys.argv) < 2):
    print('\n ### Please specify an IP address or subnet as arguments. ###')
    print(USAGE)
elif (len(sys.argv) == 2 and '/' in sys.argv[1]): # x.x.x.x/xx
        try:
            prefix = ipaddress.IPv4Network(sys.argv[1])
            urlparams = 'network?network='
        except:
            print('### Error: not a valid network address ###')
elif (len(sys.argv) == 2 and '/' not in sys.argv[1]): # x.x.x.x
        try:
            ip = ipaddress.IPv4Address(sys.argv[1])
            urlparams = 'ipv4address?status=USED&ip_address='
        except:
            print('### Error: not a valid IP address ###')
elif (len(sys.argv) == 3): # x.x.x.x x.x.x.x
    if(sys.argv[2].startswith('255.')):
        try:
            prefix = ipaddress.IPv4Network(sys.argv[1] + '/' + sys.argv[2])
            urlparams = 'network?network='
        except:
            print('### Error: not a valid network address ###')        
else:
    print('\n ### Error: too many arguments given. ###')
    print(USAGE)