Как передать словарь в качестве аргумента командной строки для python script?
Как передать словарь в качестве аргумента командной строки для python script?
Мне нужно получить словарь, где ключ - строка, а значение - список некоторых элементов
(например, чтобы выглядеть следующим образом:
command_line_arguments = {"names" : ["J.J.", "April"], "years" : [25, 29]}
Я пробовал как
if __name__ == '__main__':
args = dict([arg.split('=') for arg in sys.argv[2:]]) # also tried with 1 but doesn't work
main(args)
и я вызываю script как
$ python saver.py names=["J.J.", "April"] years=[25, 29]
но он не работает, словарь имеет длину 0 и нужен 2. Может ли кто-нибудь помочь мне передать и создать словарь в основном.
Ответы
Ответ 1
Здесь важно отметить, что в командной строке нельзя передавать объекты Python в качестве аргументов. Текущая оболочка, которую вы используете, будет анализировать аргументы и передавать их в соответствии со своими собственными правилами разбора аргументов.
При этом, вы не можете перейти в словарь Python. Тем не менее, такие вещи, как JSON, могут позволить вам быть очень близкими.
Представление объектов в формате JSON или JavaScript - это способ получения объектов Python и их преобразования в строковое представление, подходящее для передачи на несколько языков. При этом, вы можете передать в строку, как это:
python saver.py '{"names": ["J.J.", "April"], "years": [25, 29]}'
В вашем скрипте Python сделайте это:
import json
data=json.loads(argv[1])
Это вернет вам словарь, представляющий данные, которые вы хотели передать.
Кроме того, вы можете взять словарь Python и преобразовать его в строку:
import json
data={'names': ["J.J.", "April"], 'years': [25,29]}
data_str=json.dumps(data)
Есть и другие способы достижения этого, хотя JSON довольно универсален. Главное, на что нужно обратить внимание: независимо от того, как вы это сделаете - вы не будете передавать словарь в Python, - вы будете передавать набор аргументов (которые будут строками), которые вам как-то понадобятся преобразовать в нужный вам тип питона.
@EvanZamir - обратите внимание, что (как правило) в оболочке вам нужно избегать кавычек, если они появляются в вашей строке в кавычках. В моем примере я цитирую данные JSON одинарными кавычками, а сама строка json использует двойные кавычки, тем самым устраняя необходимость в кавычках.
Если вы смешиваете кавычки (используйте двойные кавычки для кавычек аргумента и двойные кавычки внутри), то оболочка потребует экранирования, в противном случае первая двойная кавычка, с которой она сталкивается, считается "закрывающей кавычкой" для аргумента. Обратите внимание, что в примере я использую одинарные кавычки для заключения строки JSON и двойные кавычки в строке. Если бы я использовал одинарные кавычки в строке, мне нужно было бы экранировать их, используя обратную косую черту, то есть:
python saver.py '{"names": ["J.J.", "April\'s"], "years": [25, 29]}'
или же
python saver.py "{\"names\": [\"J.J.\", \"April's\"], \"years\": [25, 29]}"
Обратите внимание, что цитирование - это функция вашей оболочки, поэтому YMMV может отличаться (например, если вы используете какой-либо метод exec для вызова сценария, экранирование может не потребоваться, поскольку оболочка bash может не вызываться.)
Ответ 2
Вот еще один метод с использованием стандартного ввода. Это метод, который вы хотите использовать для интерфейса json cgi (то есть веб-сервер передает запрос в ваш скрипт):
Python:
import json, sys
request = json.load( sys.stdin )
...
Чтобы проверить ваш скрипт из терминала Linux:
echo '{ "key1": "value 1", "key2": "value 2" }' | python myscript.py
Чтобы проверить ваш скрипт из терминала Windows:
echo { "key1": "value 1", "key2": "value 2" } | python myscript.py
Ответ 3
Проверьте это:
>>> from sys import argv
>>> from re import findall
>>> args = ' '.join(argv[1:])
>>> pattern = r'([^=]+)\s*=\s*\[\s*([^\]]+)\s*\]'
>>> d = dict((t[0].strip(), map(lambda x: x.strip(', '),t[1].split())) for t in findall(pattern,args))
>>> for k,v in d.items():
try: d[k] = map(int,v)
except: pass
>>> d
{'names': ['"J.J."', '"April"'], 'years': [25, 29]}
Ответ 4
Я начал с отличного ответа @chander, но столкнулся с проблемами, связанными с экранированием специальных символов, как на уровне оболочки/команды, так и внутри скрипта python. Сохранение JSON
в файл и последующая передача этого имени файла в качестве параметра в сценарий будет возможным решением, но в моей ситуации это будет довольно сложно.
Поэтому вместо этого я решил url-кодировать строку на уровне аргумента и декодировать ее внутри скрипта Python
. Это означает, что все, что вызывает скрипт python, должно кодировать URL-адрес аргумента командной строки, который является строкой JSON
. Существует множество онлайн-инструментов, которые позволяют создавать песочницу с URL-кодированием строки. В моем случае скрипт nodejs
вызывает вызов скрипта python и может легко кодировать URL JSON
.
Внутри скрипта Python
это выглядит так (вам не нужно использовать argparse
, но мне это нравится):
import json
import argparse
from urllib.parse import unquote
# Set up CLI Arguments
parser = argparse.ArgumentParser()
# Required Arguments
parser.add_argument("-c", "--config", required=True,
help="JSON configuration string for this operation")
# Grab the Arguments
args = parser.parse_args()
jsonString = unquote(args.config)
print(jsonString)
config = json.loads(jsonString)
print(config)