web-dev-qa-db-ja.com

引数を指定してsubprocess.callからアプリを呼び出す

私はPythonの初心者で、コマンドラインアプリを呼び出そうとしていますが、失敗します。

>>> import subprocess as s
>>> s.call("gpio -g read 17")
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "/usr/lib/python2.6/subprocess.py", line 470, in call
        return Popen(*popenargs, **kwargs).wait()
    File "/usr/lib/python2.6/subprocess.py", line 623, in __init__
        errread, errwrite)
    File "/usr/lib/python2.6/subprocess.py", line 1141, in _execute_child
        raise child_exception
OSError: [Errno 2] No such file or directory

しかし、Shell=Trueすべてが機能し始めます。誰かが理由を説明できますか?

>>> import subprocess as s
>>> s.call("gpio -g read 17", Shell=True)
>>> 0
28
Mark Ingram

通話権を使用していません。 はじめに またはドキュメント内の例を見てください。呼び出しの最初の引数は、引数のシーケンスである「args」です。ここで、arg [0]は実行するプログラムです。

したがって、これを行うと:

_s.call("gpio -g read 17")
_

サブプロセスがこれを解釈する方法は2つあります。引数「p」、「i」、「o」、「」などを使用して「g」というプログラムを実行する必要があります(文字列は文字のシーケンスです)。代わりに「gpio -g read」というプログラムを実行する場合があります。追加の引数なしの17インチ。どちらにしても、そのようなプログラムを見つけることはできません。 (PATHに "g"または "gpio -g read 17"と呼ばれるプログラムがある場合を除いて、この場合、エラーではなく、間違った処理が行われます...)

あなたが欲しいのは:

_s.call(["gpio", "-g", "read", "17"])
_

それで、_Shell=True_を渡すとなぜこれが機能するのですか?この文字列全体がシェルに渡されるため、シェルは独自にコマンドラインを解析し、スペースで区切ります。 os.system("gpio -g read 17")を呼び出すようなものです。

上記のすべては少し単純化されていることに注意してください(Windowsを無視し、シェルの解析は実際には「スペースで区切る」だけではないなど)。そのため、実際にドキュメントを読む必要があります。 (また、subprocess docsを書いた人は誰でも私よりも優れたライターです。)

45
abarnert