web-dev-qa-db-ja.com

これはPython内でシェルスクリプトを実行する正しい方法ですか?

import subprocess
retcode = subprocess.call(["/home/myuser/go.sh", "abc.txt", "xyz.txt"])

これらの2行を実行すると、正確にこれを実行しますか?:

/home/myuser/go.sh abc.txt xyz.txt

なぜこのエラーが発生するのですか?しかし、go.shを通常どおり実行すると、そのエラーは発生しません。

File "/usr/lib/python2.6/subprocess.py", line 480, in call
    return Popen(*popenargs, **kwargs).wait()
  File "/usr/lib/python2.6/subprocess.py", line 633, in __init__
    errread, errwrite)
  File "/usr/lib/python2.6/subprocess.py", line 1139, in _execute_child
    raise child_exception
OSError: [Errno 8] Exec format error
30
TIMEX

OSError:[Errno 8] Execフォーマットエラー

これは、/home/myuser/go.shを実行しようとしたときにオペレーティングシステムによって報告されたエラーです。

#!のShebang(go.sh)行が無効であるように見えます。

シェルから実行されるがPopenからは実行されないサンプルスクリプトを次に示します。

#\!/bin/sh
echo "You've just called $0 $@."

最初の行から\を削除すると、問題が修正されます。

33
Johnsyweb

コードを次のように変更します。

retcode = subprocess.call(["/home/myuser/go.sh", "abc.txt", "xyz.txt"], Shell=True,)

「Shell = True」に注意してください

差出人: http://docs.python.org/library/subprocess.html#module-subprocess

Unixの場合、Shell = Trueの場合:argsが文字列の場合、シェルを介して実行するコマンド文字列を指定します。つまり、文字列は、シェルプロンプトで入力したときとまったく同じようにフォーマットする必要があります。

10
jbp

私は最近、次のようなスクリプトでこの問題に遭遇しました。

% cat /tmp/test.sh
                              <-- Note the empty line
#!/bin/sh
mkdir /tmp/example

スクリプトはコマンドラインから正常に実行されましたが、

OSError: [Errno 8] Exec format error

経由で実行された場合

subprocess.Popen(['/tmp/test.sh']).communicate()

(もちろん、解決策は空の行を削除することでした)。

3
unutbu
In :call??
Signature: call(*popenargs, **kwargs)
Source:   
def call(*popenargs, **kwargs):
    """Run command with arguments.  Wait for command to complete, then
    return the returncode attribute.

    The arguments are the same as for the Popen constructor.  Example:

    retcode = call(["ls", "-l"])
    """
    return Popen(*popenargs, **kwargs).wait()
File:      /usr/lib64/python2.7/subprocess.py
Type:      function

呼び出しはPopenを呼び出すだけで、wait()メソッドを使用してpopenargsが完了するのを待ちます

1
张小诚

はい、シェルスクリプトを呼び出し、スクリプトが完了するのを待って、終了ステータスを収集し、そのstdin、stdout、およびstderrをPythonプロセスから継承するだけであれば、これでまったく問題ありません。これらの要素のいずれかをより細かく制御する必要がある場合は、より一般的な subprocess.Popen を使用しますが、それ以外の場合は問題ありません。

1
Adam Rosenfield

subprocess.callを使用して1行のスクリプトを呼び出そうとしたときに、MacOSでこのエラーが発生しました。コマンドラインから呼び出されたとき、スクリプトは正常に実行されました。シバンライン#!/usr/bin/env shを追加した後、subprocess.callを介して正常に実行されました。

シェルには実行可能とマークされたテキストファイルのデフォルトのエグゼキュータがありますが、subprocess.Popenにはありません。

1
George

はい、これは何かを実行するための好ましい方法です。

シェルによって評価される引数文字列としてではなく、配列(内部でexec()スタイルの呼び出しで使用されます)を介してすべての引数を渡すため、シェルコマンドの挿入が不可能であるため、非常に安全です。

0
ThiefMaster