Указание списка в качестве аргумента командной строки в python

Я использую getopt для обработки необязательного аргумента командной строки, который должен принимать список. Что-то вроде этого:

foo.py --my_list=[1, 2, 3, 4,5] 

Но это урезает все после "[1"

Мои вопросы: А) Есть ли способ указать список без преобразования его в строку? (используя getopt)

Б) Если я хочу преобразовать список в строку, как преобразовать этот список в строку? например, что-то вроде mylist.split("?"), чтобы избавиться от квадратных скобок?? Есть ли способ лучше?

Спасибо

6 ответов

Решение

Есть два варианта, которые я могу придумать:

  • Используйте optparse и используйте append действие, чтобы указать, что вы хотите сделать как: foo.py --my_list=1 --my_list=2 ...,
  • Укажите вашу командную строку как foo.py --my_list='1,2,3,4,5', а затем использовать x.split(',') чтобы получить ваши значения в списке. Ты можешь использовать getopt или же optparse для этого метода.

Преимущество первого метода состоит в том, что вы можете получить целочисленные значения в списке напрямую, за счет более длинной командной строки (но вы можете добавить опцию с одним символом для --my_list если ты хочешь). Преимущество второго заключается в более короткой командной строке, но после split() необходимо преобразовать строковые значения '1', '2' и т. д. до целых чисел (тоже довольно просто).

Если я не могу использовать стандартный синтаксический анализатор (optparse или argparse) для своего приложения, тогда я использую функцию ast.literal_eval для анализа входных аргументов типа list следующим образом:

import sys, ast

inputList = ast.literal_eval( sys.argv[1] )
print type( inputList )
print inputList

Предположим, что этот код хранится в файле testParser.py. Выполняя скрипт:

$ python testParser.py  "[1,2,3,4, [123, 456, 789], 'asdasd']"

мы получаем следующий вывод:

<type 'list'>
[1, 2, 3, 4, [123, 456, 789], 'asdasd']

Итак, используя достаточно безопасную функцию ast.literal_eval и вставляя список в виде строки кода, мы получаем желаемый результат.

Полезные ссылки:

Используя python eval() против ast.literal_eval()?

http://docs.python.org/2/library/functions.html?highlight=eval

Может быть, вы должны просто заключить аргумент в кавычки?

foo.py "--my_list=[1, 2, 3, 4,5]"

В противном случае каждое пространство будет рассматриваться как разделитель для аргументов.

Обновленный способ заключается в использовании argparse библиотека и добавить список в качестве аргумента командной строки. Таким образом, вам не нужно выполнять ручной анализ.

Пример:

parser = argparse.ArgumentParser()
parser.add_argument(
        "-values",
        nargs="*",  # expects ≥ 0 arguments
        type=int,
        default=[35, 40, 50, 60, 70, 80, 90],  # default list if no arg value
    )

Который вы бы тогда назвали так:

python3 someprogram.py -values 1 2 3

Со страницы помощи Python optparse: "

parser.add_option("-f")
parser.add_option("-p", type="float", nargs=3, dest="point")

Как он разбирает командную строку

-f foo.txt -p 1 -3.5 4 -fbar.txt

optparse установит

options.f = "foo.txt"
options.point = (1.0, -3.5, 4.0)
options.f = "bar.txt"

"

Я был перенаправлен с двойного вопроса:
Как передать массив в Python через командную строку - переполнение стека

Я отвечаю на этот вопрос:
Аргументы в командной строке являются строками, они не анализируются как литералы в программе.
argv автоматически создает строки в список из аргументов командной строки (разделенных пробелами), короче говоря, sys.argv это список.

    from sys import argv
    cmd = "arr = {sys.argv[1]}".format(argv)
    exec(cmd)
    print(arr[2])
Другие вопросы по тегам