Выполнение подпроцесса не выполняется

Я попытался вызвать процесс через 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 - backend are 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))

Ответ 1

Чтобы выполнить пакетный файл в 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() и проверить вывод.

Edit:

Вот что я сделал бы, если бы был вами:

a) Создайте простой Python script (testparams.py) следующим образом:

import subprocess
params = [r"C:\Program Files\Systems\Emb Work 5.4\common\bin\run.exe", ...]
print subprocess.list2cmdline(params)

b) Запустите script из командной строки (python testparams.py), скопируйте и вставьте вывод в другую командную строку, нажмите enter и посмотрите, что произойдет.

c) Если он не работает, отредактируйте файл python и повторите его, пока он не будет работать.

Ответ 2

Во-первых, вам не нужны все эти кавычки. Поэтому удалите их. Вам нужны только котировки вокруг параметров, у которых есть имя файла, когда это имя файла имеет пробел (тупо, 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 )