Не удается выполнить подпроцесс
Я пытался вызвать процесс через Python с несколькими аргументами. Само выполнение командного файла прекрасно работает, но перевод его на Python заставляет меня кричать. Вот содержимое командного файла:
"C:\Program Files\bin\cspybat" "C:\Program Files\bin\armproc.dll" "C:\Program Files\bin\armjlink.dll" "C:\Documents and Settings\USER\Desktop\CAL\testing\Verification\FRT\Code\TC1\Output\Genericb\Debug\Exe\Gen.out" --download_only --backend -B "--endian=little" "--cpu=Cortex-M3" "--fpu=None" "-p" "C:\Program Files\CONFIG\debugger\ST\iostm32f10xxb.ddf" "--drv_verify_download" "--semihosting" "--device=STM32F10xxB" "-d" "jlink" "--drv_communication=USB0" "--jlink_speed=auto" "--jlink_initial_speed=32" "--jlink_reset_strategy=0,0"
Исполняемый файл, запускаемый командным файлом, называется cspybat
, Выходные данные исполняемого файла предоставляют информацию: All parameters after
--backendare passed to the back end
,
Также обратите внимание, что некоторые параметры являются строками, а некоторые нет.
Решение
Это работает для меня сейчас:
""" MCU flashing function"""
params = [r"C:\Program Files\bin\cspy",
r"C:\Program Files\bin\arpro.dll",
r"C:\Program Files\bin\arjink.dll",
r"C:\Documents and Settings\USER\Desktop\Exe\GenerV530b.out",
"--download_only", "--backend", "-B", "--endian=little", "--cpu=Cort3", "--fpu=None", "-p",
r"C:\Program Files\CONFIG\debugger\ST\iostm32f10xxb.ddf",
"--drv_verify_download", "--semihosting", "--device=STM32F10xxB", "-d", "jlink", "--drv_communication=USB0",
"--jlink_speed=auto", "--jlink_initial_speed=32", "--jlink_reset_strategy=0,0" ]
print(subprocess.list2cmdline(params))
p = subprocess.Popen(subprocess.list2cmdline(params))
2 ответа
Чтобы выполнить командный файл в Windows:
from subprocess import Popen
p = Popen("batchfile.bat", cwd=r"c:\directory\containing\batchfile")
stdout, stderr = p.communicate()
Если вы не хотите выполнять командный файл, а хотите выполнить команду по вашему вопросу непосредственно из Python, вам нужно немного поэкспериментировать с первым аргументом Popen.
Прежде всего, первый аргумент может быть строкой или последовательностью.
Так что вы либо напишите:
p = Popen(r'"C:\Program Files\Systems\Emb Work 5.4\common\bin\run" "C:\Program Files\Systems\Emb Work 5.4\arm\bin\mpr.dll" ... ...', cwd=r"...")
или же
p = Popen([r"C:\Program Files\Systems\Emb Work 5.4\common\bin\run", r"C:\Program Files\Systems\Emb Work 5.4\arm\bin\mpr.dll", ...], cwd=r"...")
# ... notice how you don't need to quote the elements containing spaces
Согласно документации:
В Windows: класс Popen использует CreateProcess() для выполнения дочерней программы, которая работает со строками. Если args является последовательностью, она будет преобразована в строку с помощью метода list2cmdline(). Обратите внимание, что не все приложения MS Windows интерпретируют командную строку одинаково: list2cmdline() предназначен для приложений, использующих те же правила, что и среда выполнения MS C.
Так что если вы используете последовательность, она будет преобразована в строку. Сначала я бы попробовал с последовательностью, так как тогда вам не придется заключать в кавычки все элементы, содержащие пробелы (list2cmdline()
делает это для вас).
Для устранения неполадок я рекомендую передать вашу последовательность subprocess.list2cmdline()
и проверьте вывод.
Редактировать:
Вот что бы я сделал на твоем месте:
а) Создать простой скрипт на Python (testparams.py
) как это:
import subprocess
params = [r"C:\Program Files\Systems\Emb Work 5.4\common\bin\run.exe", ...]
print subprocess.list2cmdline(params)
б) Запустить скрипт из командной строки (python testparams.py
), скопируйте и вставьте вывод в другую командную строку, нажмите ввод и посмотрите, что произойдет.
c) Если это не работает, отредактируйте файл python и повторяйте, пока он не заработает.
Во-первых, вам не нужны все эти цитаты. Так что удали их. Вам нужны только кавычки вокруг параметров, которые имеют имя файла, когда это имя файла имеет пробел (глупо, Windows делает это часто).
Ваши параметры - это просто список строк, некоторые из которых требуют кавычек. Потому что Windows использует нестандартные \
для разделителя пути используйте "сырые" строки для этих имен.
params = [
r'"C:\Program Files\Systems\Emb Work 5.4\arm\bin\mpr.dll"',
r'"C:\Program Files\Systems\Emb Work 5.4\arm\bin\ajl.dll"',
r'"C:\Documents and Settings\USER\Desktop\abc.out"',
"--backend",
"-B",
"--endian=little",
"--cpu=Cortex",
"--fpu=None",
"-p",
r'"C:\Program Files\unknown\abc.ddf"',
"--drv_verify_download",
"--semihosting",
"--device=STM32F10xxB",
"-d",
"jjftk",
"--drv_communication=USB0",
"--speed=auto",
"--initial_speed=32",
"--reset_strategy=0,0"]
Используйте что-то вроде
program = r'"C:\Program Files\Systems\Emb Work 5.4\common\bin\run"'
subprocess.Popen( [program]+params )