Передача аргументов в subprocess.call

Столкнулся с неприятной ситуацией с тихой установкой какой-то программы. Я не уверен, что они используют какое-либо соглашение для установки флагов со значениями, но вот что следует использовать для установки:

"path with spaces\setup.exe" -uninst -s -f2"path with spaces\uninstall.log"

вы не можете использовать --f2="путь с пробелами\uninstall.log" или -f2="путь с пробелами\uninstall.log" или -f2 "путь с пробелами\uninstall.log"

поэтому, если я использую в Python следующее:

command = [self.setup_exe, '-uninst', '-s', fr'-f2"{uninstall_log_file}"']

команда, которую выполняет подпроцесс (получить из subprocess.list2cmdline(command)):

setup.exe" -uninst -s -f2\"some path\temp build 12\uninstall.log\"

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


person Beliaev Maksim    schedule 19.06.2020    source источник
comment
Как вы на самом деле вызываете команду? Похоже, вы используете shell=True, когда этого делать не следует.   -  person chepner    schedule 19.06.2020
comment
@chepner, вы правы, я использую shell=True. Насколько я понял, это нужно в случае, если мне нужно запустить команду от имени пользователя с повышенными правами (например, с помощью PowerShell). Или сработает в любом случае?   -  person Beliaev Maksim    schedule 19.06.2020
comment
Нет, использование shell=True просто переключает от выполнения команды непосредственно к запуску оболочки со сконструированным аргументом, чтобы оболочка выполняла команду для вас.   -  person chepner    schedule 19.06.2020
comment
вот как я сейчас звоню: subprocess.call(command)   -  person Beliaev Maksim    schedule 19.06.2020
comment
@chepner, теперь он создает еще один слой кавычек: -f2\some path\uninstall.log\   -  person Beliaev Maksim    schedule 19.06.2020
comment
Вы включили кавычки в свое определение command: fr'-f2"{uinstall_log_file}"'. Вы можете опустить их.   -  person chepner    schedule 19.06.2020
comment
@chepner, к сожалению, нет, тогда он обрабатывает весь аргумент как пробел и делает -f2path..... Не работает :(   -  person Beliaev Maksim    schedule 20.06.2020
comment
Каково фактическое значение uninstall_log_file и какую фактическую команду вы используете для запуска исполняемого файла?   -  person chepner    schedule 20.06.2020
comment
@chepner, см. первую команду в вопросе. По сути, это может быть любой путь, содержащий пробел. Путь запрашивается у пользователя. Например, C:\Test 1 2 3 4\log.log.   -  person Beliaev Maksim    schedule 20.06.2020
comment
Вот как вы можете вызвать его из командной строки оболочки. Какой фактический код Python вы используете для запуска команды?   -  person chepner    schedule 20.06.2020
comment
Кажется, я ответил. subprocess.call(команда). Я пробовал и в оболочке, и без оболочки   -  person Beliaev Maksim    schedule 22.06.2020
comment
Тогда проблема заключается в вашем определении command, как я указал ранее. Вы добавляете кавычки, чтобы помешать оболочке обработать значение uninstall_log_file, но нет такой оболочки. Попробуйте command = [..., '-f2', uninstall_log_file].   -  person chepner    schedule 22.06.2020
comment
Я готов отказаться от синтаксиса, используемого для этого молчания. Легче построить строку самому. Я не думаю, что это возможно через список   -  person Beliaev Maksim    schedule 22.06.2020
comment
@chepner, нет, я не могу его использовать. Невозможно иметь пробел между -f2 и путем   -  person Beliaev Maksim    schedule 22.06.2020
comment
Как и в вопросе: вы не можете использовать --f2=путь с пробелами\uninstall.log или -f2=путь с пробелами\uninstall.log или -f2 путь с пробелами\uninstall.log   -  person Beliaev Maksim    schedule 22.06.2020


Ответы (1)


Если вы запустите

"path with spaces\setup.exe" -uninst -s -f2"path with spaces\uninstall.log"

из командной строки эквивалентный вызов subprocess.call

uninstall_log_file = r"path with spaces\uninstall.log"
command = [self.setup_exe, '-uninst', '-s', f'-f2{uninstall_log_file}']
subprocess.call(command)
person chepner    schedule 21.06.2020
comment
к сожалению, это плохо не работает, я уже пробовал это. Если я укажу путь без пробелов, он будет работать. Если я укажу путь с пробелами, то нет, так как аргумент будет выглядеть как -f2path с пробелами/log.log. Так что это не работает - person Beliaev Maksim; 22.06.2020
comment
Я также пробовал это: stackoverflow.com/questions/43022687/ однако я предполагаю разницу в провайдере. Так как там аргумент будет выглядеть как -f2=путь с пробелами. В моем примере из CMD знак равенства не допускается - person Beliaev Maksim; 22.06.2020
comment
Я немного изменил ответ, сделав uninstall_log_file необработанной строкой, а не f-строкой, которая интерполирует значение. Я не уверен, что это изменит ситуацию. - person chepner; 22.06.2020
comment
только что провел тест. К сожалению нет. Я выполнил подпроцесс со списком, но для проверки также запустил list2cmdline. Он добавляет кавычки вокруг -f2 -> -f2path. Так что установка не проходит. что работает, но странно: command = [f'{self.setup_exe}', '-uninst', '-s', fr'-f2{uninstall_log_file}'] command = .join(command), а затем вызовите подпроцесс с помощью строка. Как вы думаете, можно ли получить то же самое, используя список? - person Beliaev Maksim; 23.06.2020