Не удается выполнить подпроцесс - PullRequest
16 голосов
/ 30 ноября 2009

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

Ответы [ 2 ]

24 голосов
/ 30 ноября 2009

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

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

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

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

0 голосов
/ 30 ноября 2009

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