web-dev-qa-db-ja.com

サブプロセスの実行に失敗する

いくつかの引数を使用して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--バックエンド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))
16
binaryguy

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()メソッドを使用して文字列に変換されます。すべてのMSWindowsアプリケーションがコマンドラインを同じように解釈するわけではないことに注意してください。list2cmdline()は、MSCランタイムと同じルールを使用するアプリケーション用に設計されています。

したがって、シーケンスを使用すると、文字列に変換されます。スペースを含むすべての要素を引用する必要がないので、おそらく最初にシーケンスを試してみます(list2cmdline()がそれを行います)。

トラブルシューティングのために、シーケンスをsubprocess.list2cmdline()に渡して、出力を確認することをお勧めします。

編集:

私があなただったら、これが私がすることです:

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_)からスクリプトを実行し、出力をコピーして別のコマンドラインに貼り付け、Enterキーを押して何が起こるかを確認します。

c)機能しない場合は、pythonファイルを編集し、機能するまで繰り返します。

24
codeape

まず、これらすべての引用符は必要ではありません。だからそれらを削除します。ファイル名にスペースがある場合にのみ、ファイル名を持つパラメーターを引用符で囲む必要があります(愚かなことに、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 )
0
S.Lott