Запустите команду bash с переменными в качестве подпроцесса python

#python #bash #algolia

#python #bash #algolia

Вопрос:

У меня есть эта команда оболочки:

$ docker run -it --env-file=.env -e "CONFIG=$(cat /path/to/your/config.json | jq -r tostring)" algolia/docsearch-scraper

И я хочу запустить ее как подпроцесс python. Я думал, что мне понадобится только эквивалент jq -r tostring , но если я использую config.json как обычную строку, » не экранируется. Я также избежал их, используя json.load(config.json). С помощью исходной команды jq » тоже не экранируется, и она просто возвращает строку json.

Когда я использую json, возвращаемый в виде строки в подпроцессе python, я всегда получаю FileNotFoundError в строке подпроцесса.

 @main.command()
def algolia_scrape():
    with open(f"{WORKING_DIR}/conf_dev.json") as conf:
        CONFIG = json.load(conf)
        subprocess.Popen(f'/usr/local/bin/docker -it --env-file={WORKING_DIR}/algolia.env -e "CONFIG={json.dumps(CONFIG)}" algolia/docsearch-scraper')
  

Ответ №1:

Вы получаете «файл не найден», потому что (без shell=True ) вы пытаетесь запустить команду, имя /usr/local/bin/docker -it ... которой указано, когда вы хотите выполнить /usr/local/bin/docker с некоторыми аргументами. И, конечно, было бы в значительной степени кошмаром пытаться передать JSON через оболочку, потому что вам нужно экранировать любые метасимволы оболочки из строки; но просто разбейте командную строку на список строк, как это сделала бы оболочка.

 def algolia_scrape():
    with open(f"{WORKING_DIR}/conf_dev.json") as conf:
        CONFIG = json.load(conf)
    p = subprocess.Popen(['/usr/local/bin/docker', '-it',
        f'--env-file={WORKING_DIR}/algolia.env',
        '-e', f'CONFIG={json.dumps(CONFIG)}',
        'algolia/docsearch-scraper'])
  

Обычно вы хотите сохранить результат subprocess.Popen() , потому что вам нужно будет wait для процесса, когда он завершится.

Комментарии:

1. Возможно, можно было бы избежать циклической загрузки / сброса, поместив буквальный текст файла конфигурации (с удалением любого завершающего пробела) в командной строке.

2. Спасибо. Это было все. Но теперь я получаю «Неизвестный сокращенный флаг «i» в нем». У кого-нибудь есть обходной путь и для этого?

3. Я полагаю, вы имели в виду docker run -it ?