Как я могу заставить сценарий Python анализировать аргументы командной строки, например команду Unix?

У меня есть служебный скрипт Python, который принимает аргументы в командной строке и выполняет задачи с помощью поискового инструмента с открытым исходным кодом, который называется Elasticsearch.

Но, проще говоря, вот как он сейчас используется:

Myscript.py create indexname http://localhost:9260
Myscript.py create indexname http://localhost:9260 IndexMap.json

Я хотел бы сделать так, чтобы пользователю сценария не приходилось запоминать порядок аргументов сценария. Как я могу включить это в моем скрипте? Я думал о передаче аргументов в стиле Unix. Например:

import os
import sys
import glob
import subprocess 

# collect command line arguments
commandline_args = sys.argv

# How to use this simple API:
#   create indexname http://localhost:9260 IndexMap.json

command_type = commandline_args[1]
index_name = commandline_args[2]
base_elasticsearch_url = commandline_args[3]
file_to_index = sys.argv[4] if len(sys.argv) > 4 else None


def run_curl(command, url):
    cmd = ['curl', command]
    url = url.split(' ')
    print 'sending command: '
    print cmd+url    
    return subprocess.check_output(cmd+url)

if (command_type == 'delete'):
    print 'About to run '+ command_type + ' on Index: ' + index_name
    command = '-XDELETE'
    composed_url = base_elasticsearch_url + '/' + index_name + '/'
    output = run_curl(command, composed_url)
    print 'output:'
    print output

# create Index # works!
# curl -XPOST 'localhost:9260/icrd_client_1 -d @clientmappings.json
if (command_type == 'create'):
    print 'About to run '+command_type+' for Index: '+index_name+' from filename: '+file_to_index
    command = '-XPOST'
    composed_url = base_elasticsearch_url + '/' + index_name +' -d ' + '@'+file_to_index
    output = run_curl(command, composed_url)
    print 'output:'
    print output

person Horse Voice    schedule 29.10.2013    source источник
comment
import argparse было бы хорошим местом для начала.   -  person rlms    schedule 29.10.2013
comment
@sweeneyrod argparse требуется версия 2.7 или новее.   -  person ely    schedule 29.10.2013


Ответы (3)


Если вы используете Python 2.7 или новее, попробуйте argparse. Для более старых версий попробуйте optparse

person ely    schedule 29.10.2013
comment
У меня питон: 2.7.5. Argparse похож на очень неуклюжего мамонта. не могли бы вы привести пример того, как я могу использовать это в своем коде? Мне больше нужен sys.argv? - person Horse Voice; 29.10.2013
comment
Я не понимаю комментарий. Argparse выглядит очень неуклюжим мамонтом. Можете быть более конкретными? - person ely; 29.10.2013
comment
Что ж, мой реальный вопрос в том, есть ли лучший учебник, который я могу использовать для argparse .. Тот, который находится на сайте python, является справочным, и я не эксперт в python. Есть какие-нибудь быстрые простые уроки по этой теме? - person Horse Voice; 29.10.2013
comment
Является ли это руководство более полезным? - person ely; 29.10.2013
comment
args = parser.parse_args() ‹★ что именно это делает? В моем примере я могу получить доступ к записям командной строки следующим образом: command_type = commandline_args[1] .. Я не понимаю, что такое parser.parse_args () .. - person Horse Voice; 29.10.2013
comment
Откройте интерпретатор Python и попробуйте. Разобраться несложно. Создайте простую программу, подобную той, что описана в руководстве, а затем просто начните передавать аргументы командной строки и печатать материал. - person ely; 29.10.2013
comment
Я не понимаю, как это позволит независимость порядка? - person Horse Voice; 29.10.2013

Я предлагаю простое элегантное решение с использованием словаря Python Dictionary, вы можете использовать словарь key вместо оператора if, это не лучший вариант, я уверен, что он просто немного более элегантен.

import sys

def func1():
    print "I'm func1"

def func2():
    print "I'm func2"

def func3():
    print "I'm func3"

def func4():
    print "I'm default!"

def main():

    myCommandDict = {"arg1": func1(), "arg2": func2(), "arg3": func3(), "default": func4()}

    commandline_args = sys.argv

    for argument in commandline_args[1]:
        if argument in myCommandDict:
            myCommandDict[argument]
        else:
            myCommandDict["default"]

if __name__ == "__main__":
    main()

Edit main можно заменить этой опцией:

myCommandDict = {"arg1": func1, "arg2": func2, "arg3": func3, "default": func4}

commandline_args = sys.argv[1:]

for argument in commandline_args:
    if argument in myCommandDict:
        myCommandDict[argument]()
    else:
        myCommandDict["default"]()
person Kobi K    schedule 29.10.2013
comment
Для меня это не имеет смысла. У вас есть вызовы функций как значения в словаре, поэтому у вас есть {"arg1": None, "arg2": None, "arg3": None, "default": None}. Я думаю, ты хочешь вместо этого "arg1: func1 и myCommandDict[argument](). Кроме того, вы можете заменить ключ "default", используя myCommandDict.get(argument, func4)() вместо операторов if else. - person rlms; 29.10.2013
comment
@sweeneyrod Он может работать в обоих направлениях (проверено), но я внес изменения в другой вариант, как вы предложили, и я должен сказать, что это лучший подход. - person Kobi K; 29.10.2013

Вы также можете использовать Getopt (он работает аналогично GNU Getopt)

person Bezzi    schedule 29.10.2013