2016-11-26 3 views
0

В настоящее время я пишу скрипт для своей библиотеки, и я в конечном итоге зациклился на том, как создавать argparse, который будет иметь множество опций и вспомогательных аргументов.Конструирование argparse со многими необязательными подпараметрами

В настоящее время я проектирования функцию поиска, которая имеет следующие параметры, некоторые необходимые и некоторые нет:

  • search_session_id - Требуется
  • user_session_id - Требуется
  • discover_fields - Факультативные
  • start_time - Дополнительный
  • end_time - необязательный
  • summary_fields - дополнительно
  • field_summary - Дополнительный
  • local_search - Дополнительный

Моя проблема тогда следующее:

Как я могу сделать argparse и если заявления, если все OPTIONALS нужно работать вместе, но и работать, если определен только один из них?

Если мне нужно проверять каждую комбинацию, я бы в конечном итоге с чем-то вроде этого:

#!/usr/bin/env python3 

"""Script to generate searches on the ArcSight Logger""" 

import arcsightrest 
import argparse 

parser = argparse.ArgumentParser(description='Script used to send search ' 
              'queries to ArcSight Logger API') 
parser.add_argument('-t', '--target', 
        help='IP Address of the Loggger', required=True) 
parser.add_argument('-u', '--username', 
        help='Username to access the logger', required=True) 
parser.add_argument('-p', '--password', 
        help='Password to access the logger', required=True) 
parser.add_argument('-ussl', '--unsecuressl', action='store_true', 
        help='Disable ssl warnings',) 
parser.add_argument('-w', '--wait', action='store_true', 
        help='Wait for query to finish',) 
parser.add_argument('-q', '--query', 
        help='Query to be used in the search') 
parser.add_argument('-st', '--starttime', 
        help='From which time the query should look') 
parser.add_argument('-et', '--endtime', 
        help='To which time the query should look') 
parser.add_argument('-e', '--event', 
        help='Events based input search id') 
parser.add_argument('-s', '--status', 
        help='Status of running search') 
args = (parser.parse_args()) 

""" 
Sets the target Logger Server 
""" 
arcsightrest.ArcsightLogger.TARGET = args.target 

""" 
Gets login token from the Logger API 
""" 
arc = arcsightrest.ArcsightLogger(args.username, args.password, 
            args.unsecuressl) 
""" 
Checks if query is used, and starts a search 
""" 
if args.query: 
    if args.starttime: 
     search_id, response = arc.search(args.query, start_time=args.starttime, 
             end_time=args.endtime) 
    search_id, response = arc.search(args.query) 

    if args.starttime and args.discover_fields: 
     search_id, response = arc.search(args.query, start_time=args.starttime, 
             end_time=args.endtime, 
             discover_fields=args.discover_fields) 
    print('The search id is {}'.format(search_id)) 
    if response: 
     print('The search has successfully started') 

Как вы можете видеть, я могу продолжать без конца, чтобы сделать если заявления, которые имеют каждый сочетание необязательных аргументов. Должен быть более простой способ разработать это? Если бы я просто разбирал его как kwargs, они не отправлялись в правильном формате, или я бы потребовал, чтобы человек, использующий скрипт, писал такие вещи, как end_time=SOMETIME, а не только --endtime TIME. Теперь это может показаться небольшой ценой, но если мне нужно добавить каждую функцию со всеми их параметрами в скрипт, то это будет намного дольше и утомительно.

+0

Как насчет подкоманд? https://docs.python.org/3.5/library/argparse.html#sub-commands – errikos

ответ

2

Вы можете собрать все дополнительные именованные аргументы, передаваемые arc.search в dict, а затем распаковать его при вызове функции:

import argparse 

parser = argparse.ArgumentParser(description='Script used to send search ' 
              'queries to ArcSight Logger API') 
parser.add_argument('-t', '--target', 
        help='IP Address of the Loggger', required=True) 
parser.add_argument('-u', '--username', 
        help='Username to access the logger', required=True) 
parser.add_argument('-p', '--password', 
        help='Password to access the logger', required=True) 
parser.add_argument('-q', '--query', 
        help='Query to be used in the search') 
parser.add_argument('-st', '--starttime', 
        help='From which time the query should look') 
parser.add_argument('-et', '--endtime', 
        help='To which time the query should look') 
args = (parser.parse_args()) 

# Mock search 
def search(query, start_time=None, end_time=None, discover_fields=None): 
    return 'Id', ', '.join(str(x) for x in [start_time, end_time, discover_fields]) 

""" 
Checks if query is used, and starts a search 
""" 
if args.query: 
    # {name used in argparse: search parameter name} 
    query_args = { 
     'starttime': 'start_time', 
     'endtime': 'end_time', 
     'discover_fields': 'discover_fields' 
    } 
    d = vars(args) 
    real_args = {v: d[k] for k, v in query_args.items() if k in d} 
    search_id, response = search(args.query, **real_args) 

    print('The search id is {}'.format(search_id)) 
    print('Response is {}'.format(response)) 

Выход:

>python test.py -t foo -u user -p pass -q 
query -st start -et end 
The search id is Id 
Response is start, end, None 

Поскольку некоторые из имен аргументов используемые парсером, отличаются от тех, которые были переданы в search, имена должны быть переназначены. vars Используется для создания dict от Namespace Объект, полученный parse_args(). Затем понимание словаря повторяется над именами сопоставленных аргументов, выбирает те, которые были предоставлены пользователю, и создает новый словарь с именами клавиш, которые понимает arc.search. Наконец **real_args распаковывает словарь с именами параметров в вызове функции.