Wykonanie podprocesu nie powiodło się

Próbowałem wywołać proces przez Pythona z kilkoma argumentami. Wykonanie samego pliku wsadowego działa mi dobrze, ale tłumaczenie go na Python sprawia, że krzyczę. Tutaj zawartość pliku wsadowego:

"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" 

Plik wykonywalny uruchamiany przez plik wsadowy nosi nazwę cspybat. Wyjście pliku wykonywalnego dostarcza informacji: All parameters after--backend are passed to the back end.

Zauważ również, że niektóre z parametrów są ciągami znaków, a niektóre nie.

rozwiązanie

To działa na ja teraz:

    """ 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))
Author: Robert MacLean, 2009-11-30

2 answers

Aby uruchomić plik wsadowy w systemie Windows:

from subprocess import Popen
p = Popen("batchfile.bat", cwd=r"c:\directory\containing\batchfile")
stdout, stderr = p.communicate()

Jeśli nie chcesz wykonać pliku wsadowego, a raczej wykonać polecenie w Pythonie bezpośrednio z Pythona, musisz trochę poeksperymentować z pierwszym argumentem Popen.

Po pierwsze, pierwszy argument może być łańcuchem lub sekwencją.

Więc albo piszesz:

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"...")

Lub

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

Zgodnie z dokumentacją:

W systemie Windows: Klasa Popen używa CreateProcess() do wykonania program potomny, który działa na strunach. Jeśli args jest sekwencją, zostanie ona przekonwertowana na łańcuch za pomocą metody list2cmdline (). Należy pamiętać, że nie wszystkie aplikacje MS Windows interpretują wiersz poleceń w ten sam sposób: list2cmdline() jest przeznaczona dla aplikacji używających tych samych reguł co ms C runtime.

Więc jeśli użyjesz sekwencji, zostanie ona przekonwertowana na ciąg znaków. Prawdopodobnie najpierw spróbowałbym z sekwencją, ponieważ wtedy nie będziesz musiał cytować wszystkich elementów, które zawierają spacje (list2cmdline() robi to za Ciebie).

W przypadku rozwiązywania problemów, zalecam podanie sekwencji do subprocess.list2cmdline() i sprawdzenie wyjścia.

Edit:

Oto co bym zrobił na Twoim miejscu:

A) Utwórz prosty skrypt Pythona (testparams.py) w następujący sposób:

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

B) Uruchom skrypt z linii poleceń (python testparams.py), skopiuj i wklej wyjście do innej linii poleceń, naciśnij enter i zobacz, co się stanie.

C) jeśli to nie działa, Edytuj plik Pythona i powtarzaj, aż działa.

 24
Author: codeape,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-30 19:34:28

Po pierwsze, nie potrzebujesz tych wszystkich cytatów. Więc je usuń. Potrzebujesz cudzysłowów wokół parametrów, które mają nazwę pliku, tylko wtedy, gdy nazwa pliku ma spację (głupio, Windows robi to często).

Twoje parametry są po prostu listą łańcuchów, z których niektóre wymagają cudzysłowów. Ponieważ system Windows używa niestandardowych znaków \ dla separatora ścieżek, dla tych nazw należy użyć "raw".

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"]

Użyj czegoś w rodzaju

program = r'"C:\Program Files\Systems\Emb Work 5.4\common\bin\run"'
subprocess.Popen( [program]+params )
 0
Author: S.Lott,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-30 19:14:50