web-dev-qa-db-ja.com

Pythonで外部コマンドを呼び出す

Pythonスクリプト内から(UnixシェルまたはWindowsのコマンドプロンプトで入力した場合と同じように)外部コマンドを呼び出す方法を教えてください。

4038
freshWoWer

標準ライブラリの サブプロセスモジュール を見てください。

import subprocess
subprocess.run(["ls", "-l"])

subprocess vs. system の利点は、より柔軟であるということです(標準出力、標準エラー出力、 "実際の"ステータスコード、より良いエラー処理などが得られます) 。

公式ドキュメント は、代わりのos.system()よりも サブプロセス モジュールを推奨します。

サブプロセス モジュールは、新しいプロセスを生成してその結果を取得するためのより強力な機能を提供します。そのモジュールを使うことはこの関数を使うより好ましいです[ os.system() ]。

subprocess のドキュメントの " より古い関数をsubprocessモジュール に置き換える"セクションには役に立つレシピがいくつかあります。

3905

外部プログラムを呼び出す方法とそれぞれの長所と短所は次のとおりです。

  1. os.system("some_command with args")は、コマンドと引数をシステムのシェルに渡します。実際にこの方法で一度に複数のコマンドを実行し、パイプと入出力リダイレクトを設定できるので、これは素晴らしいことです。例えば: 

    os.system("some_command < input_file | another_command > output_file")  
    

    ただし、これは便利ですが、スペースなどのシェル文字のエスケープを手動で処理する必要があります。一方、これにより、単にシェルコマンドであり、実際には外部プログラムではないコマンドも実行できます。 ドキュメント を参照してください。

  2. stream = os.popen("some_command with args")os.systemと同じことをしますが、そのプロセスの標準入出力にアクセスするために使用できるファイルのようなオブジェクトを提供します。 popenには他に3つの変種があり、それらはすべて入出力をわずかに異なる方法で処理します。すべてを文字列として渡すと、コマンドはシェルに渡されます。それらをリストとして渡しても、何もエスケープする必要はありません。 ドキュメント を参照してください。

  3. Popenモジュールのsubprocessクラス。これはos.popenの代わりになることを意図していますが、非常に包括的であるために少し複雑になるという欠点があります。たとえば、次のようになります。

    print subprocess.Popen("echo Hello World", Shell=True, stdout=subprocess.PIPE).stdout.read()
    

    の代わりに: 

    print os.popen("echo Hello World").read()
    

    しかし、4つの異なるpopen関数ではなく、1つの統一されたクラスにすべてのオプションがあるのはいいことです。 ドキュメント を参照してください。

  4. callモジュールからのsubprocess関数。これは基本的にPopenクラスと全く同じで、すべて同じ引数を取りますが、単にコマンドが完了して戻りコードを受け取るまで待機します。例えば:

    return_code = subprocess.call("echo Hello World", Shell=True)  
    

    ドキュメント を参照してください。

  5. Python 3.5以降を使用している場合は、新しい subprocess.run 関数を使用できます。これは上記によく似ていますが、より柔軟で、コマンドの実行が終了すると CompletedProcess オブジェクトを返します。

  6. Osモジュールには、Cプログラムにあるはずのfork/exec/spawn関数もすべて含まれていますが、それらを直接使用することはお勧めしません。

subprocessモジュールはおそらくあなたが使うものであるべきです。

最後に、シェルが文字列として実行する最後のコマンドを渡すすべてのメソッドについて、それをエスケープする責任があることに注意してください。渡した文字列の一部が完全に信頼できない場合は、深刻なセキュリティ上の影響があります。たとえば、ユーザーが文字列の一部または任意の部分を入力しているとします。よくわからない場合は、これらのメソッドを定数でのみ使用してください。あなたに影響のヒントを与えるためにこのコードを考慮してください:

print subprocess.Popen("echo %s " % user_input, stdout=PIPE).stdout.read()

ユーザーが「私のママは私を愛していなかった&& rm -rf /」と入力したとします。

2665
Eli Courtwright

私は通常使用します:

import subprocess

p = subprocess.Popen('ls', Shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in p.stdout.readlines():
    print line,
retval = p.wait()

パイプ内のstdoutデータを使用して自由に実行できます。実際、これらのパラメータ(stdout=stderr=)は単に省略することができ、それはos.system()のように振る舞います。

292
EmmEff

子プロセスを呼び出し元のプロセスから切り離すことについてのいくつかのヒント(子プロセスをバックグラウンドで開始する)。

CGIスクリプトから長いタスクを開始したいとします。つまり、子プロセスはCGIスクリプトの実行プロセスよりも長く存続するはずです。

サブプロセスモジュールdocsからの古典的な例は次のとおりです。

import subprocess
import sys

# some code here

pid = subprocess.Popen([sys.executable, "longtask.py"]) # call subprocess

# some more code here

ここでの考えは、longtask.pyが終了するまで 'call subprocess'の行を待つのを避けたいということです。しかし、例の「some more code here」の行の後に何が起こるかは明確ではありません。

私のターゲットプラットフォームはfreebsdでしたが、開発はWindows上でしたので、私は最初にWindows上の問題に直面しました。

ウィンドウズ(win xp)では、longtask.pyが作業を終了するまで親プロセスは終了しません。それはあなたがCGIスクリプトで欲しいものではありません。問題はPythonに固有のものではなく、PHPコミュニティでも問題は同じです。

解決策は、win APIの基礎となるCreateProcess関数にDETACHED_PROCESS Process Creation Flag を渡すことです。 pywin32をインストールしたことがある場合は、win32processモジュールからフラグをインポートできます。 :

DETACHED_PROCESS = 0x00000008

pid = subprocess.Popen([sys.executable, "longtask.py"],
                       creationflags=DETACHED_PROCESS).pid

/ * UPD 2015.10.27 以下のコメントにある@eryksun、意味的に正しいフラグはCREATE_NEW_CONSOLE(0x00000010)であることを示します* /

Freebsdでは、もう1つ問題があります。親プロセスが終了すると、子プロセスも終了します。そしてそれはあなたがCGIスクリプトでも望んでいることではありません。いくつかの実験は、問題がsys.stdoutの共有にあるように思われることを示しました。実用的な解決策は次のとおりです。

pid = subprocess.Popen([sys.executable, "longtask.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)

私は他のプラットフォームでコードをチェックしていないし、freebsdの動作の理由を知りません。誰かが知っているなら、あなたの考えを共有してください。 Pythonでバックグラウンドプロセスを開始することに関するグーグルは、まだ何も明らかにしていません。

186
newtover
import os
cmd = 'ls -al'
os.system(cmd)

コマンドの結果を返したい場合は、 os.popen を使用できます。しかし、これはバージョン2.6以降では推奨されていません。 サブプロセスモジュール の方が有利です。

113

Os.systemの代わりにサブプロセスモジュールを使用することをお勧めします。シェルがエスケープしてくれるので、より安全だからです。 http://docs.python.org/library/subprocess.html

subprocess.call(['ping', 'localhost'])
113
sirwart
import os
os.system("your command")

これは危険であることに注意してください、コマンドがきれいにされないので。 「os」および「sys」モジュールに関する関連文書については、Googleにお任せください。似たようなことをするたくさんの関数(exec *とspawn *)があります。

101
nimish

Pythonで外部コマンドを呼び出せるようにするライブラリはたくさんあります。各ライブラリについて説明し、外部コマンドを呼び出す例を示しました。例として使用したコマンドはls -l(すべてのファイルを一覧表示)です。あなたが私がリストアップし、それぞれのためのドキュメンテーションをリンクしたライブラリーのどれかについてもっと知りたいならば。

出典:

これらはすべてライブラリです:

うまくいけば、これはあなたがどのライブラリを使用するかについての決定を下すのを助けるでしょう:)

サブプロセス

サブプロセスを使用すると、外部コマンドを呼び出してそれらを入力/出力/エラーパイプ(stdin、stdout、およびstderr)に接続できます。サブプロセスは、コマンドを実行するためのデフォルトの選択ですが、他のモジュールの方が優れていることもあります。

subprocess.run(["ls", "-l"]) # Run command
subprocess.run(["ls", "-l"], stdout=subprocess.PIPE) # This will run the command and return any output
subprocess.run(shlex.split("ls -l")) # You can also use the shlex library to split the command

os

osは「オペレーティングシステムに依存する機能」に使用されます。 os.systemos.popenを使って外部コマンドを呼び出すためにも使用できます(注:subprocess.popenもあります)。 osは常にシェルを実行し、subprocess.runを使用する必要がない、または使用方法がわからない人々のための単純な代替手段です。

os.system("ls -l") # run command
os.popen("ls -l").read() # This will run the command and return any output

sh

shは、プログラムを関数のように呼び出すことができるサブプロセスインタフェースです。これは、コマンドを複数回実行したい場合に便利です。

sh.ls("-l") # Run command normally
ls_cmd = sh.Command("ls") # Save command as a variable
ls_cmd() # Run command as if it were a function

plumbumは "スクリプトのような" Pythonプログラム用のライブラリです。 shのように関数のようなプログラムを呼び出すことができます。あなたがシェルなしでパイプラインを走らせたいならPlumbumは役に立ちます。

ls_cmd = plumbum.local("ls -l") # get command
ls_cmd() # run command

pexpect

pexpectを使用すると、子アプリケーションを起動し、それらを制御し、その出力からパターンを見つけることができます。これはUnix上でttyを期待するコマンドのサブプロセスに代わるより良い方法です。

pexpect.run("ls -l") # Run command as normal
child = pexpect.spawn('scp foo [email protected]:.') # Spawns child application
child.expect('Password:') # When this is the output
child.sendline('mypassword')

ファブリック

fabricはPython 2.5と2.7のライブラリです。ローカルとリモートのシェルコマンドを実行できます。ファブリックは、セキュアシェル(SSH)でコマンドを実行するための単純な代替手段です。

fabric.operations.local('ls -l') # Run command as normal
fabric.operations.local('ls -l', capture = True) # Run command and receive output

特使

使節は「人間のためのサブプロセス」として知られています。これはsubprocessモジュールの便利なラッパーとして使われています。

r = envoy.run("ls -l") # Run command
r.std_out # get output

コマンド

commandsにはos.popenのラッパー関数が含まれていますが、subprocessがより良い代替手段であるため、Python 3から削除されました。

編集はJ.F. Sebastianのコメントに基づいていました。

63
Tom Fuller

私はいつもこのようなことのためにfabricを使います:

from fabric.operations import local
result = local('ls', capture=True)
print "Content:/n%s" % (result, )

しかしこれは良いツールのようです: sh(Pythonサブプロセスインタフェース)

例を見てください。

from sh import vgdisplay
print vgdisplay()
print vgdisplay('-v')
print vgdisplay(v=True)
60

"pexpect" Pythonライブラリも調べてください。

Ssh、ftp、telnetなど、外部のプログラムやコマンドをインタラクティブに制御することができます。

child = pexpect.spawn('ftp 192.168.0.24')

child.expect('(?i)name .*: ')

child.sendline('anonymous')

child.expect('(?i)password')
59
athanassis

あなたが呼び出しているコマンドの出力が必要ならば、そして subprocess.check_output (Python 2.7+)を使うことができます。

>>> subprocess.check_output(["ls", "-l", "/dev/null"])
'crw-rw-rw- 1 root root 1, 3 Oct 18  2007 /dev/null\n'

Shell パラメータにも注意してください。

ShellがTrueの場合、指定されたコマンドはシェルを介して実行されます。これは、Pythonをほとんどのシステムシェルで提供される拡張制御フローに主に使用していて、シェルパイプ、ファイル名のワイルドカード、環境変数の展開、ユーザーの自宅への〜などの他のシェル機能への便利なアクセスが必要な場合ディレクトリ。ただし、Python自体が多くのシェル風の機能(特に、globfnmatchos.walk()os.path.expandvars()os.path.expanduser()、およびshutil)の実装を提供していることに注意してください。

53
Facundo Casco

標準ライブラリとは

Use サブプロセスモジュール (Python 3):

import subprocess
subprocess.run(['ls', '-l'])

これはお勧めの標準的な方法です。しかし、もっと複雑なタスク(パイプ、出力、入力など)は、作成して書くのが面倒です。

Pythonバージョンに関する注意:まだPython 2を使用している場合、 subprocess.call は同様に機能します。

ProTip: shlex.split は、runcall、およびその他のsubprocess関数について、コマンドを解析してリストの形式で提供したくない場合に役立ちます。

import shlex
import subprocess
subprocess.run(shlex.split('ls -l'))

外部依存関係を持つ

外部の依存関係を気にしないのであれば、 plumbum を使用してください。

from plumbum.cmd import ifconfig
print(ifconfig['wlan0']())

それは最高のsubprocessラッパーです。クロスプラットフォームです。つまり、WindowsとUnixの両方のシステムで動作します。 pip install plumbumでインストールしてください。

他の人気のあるライブラリは sh :です。

from sh import ifconfig
print(ifconfig('wlan0'))

しかし、shはWindowsのサポートをやめたので、以前のようにそれほど素晴らしいものではありません。 pip install shでインストールしてください。

51
Honza Javorek

更新:

subprocess.runが推奨されるアプローチです Python 3.5以降 コードが以前のPythonバージョンとの互換性を維持する必要がない場合より一貫性があり、Envoyと同様の使いやすさを提供します。 (ただし、配管はそれほど単純ではありません。 方法についてはこの質問 を参照してください。)

ドキュメント の例をいくつか示します。

プロセスを実行します。

>>> subprocess.run(["ls", "-l"])  # doesn't capture output
CompletedProcess(args=['ls', '-l'], returncode=0)

失敗した実行時に発生する:

>>> subprocess.run("exit 1", Shell=True, check=True)
Traceback (most recent call last):
  ...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1

出力をキャプチャする:

>>> subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE)
CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0,
stdout=b'crw-rw-rw- 1 root root 1, 3 Jan 23 16:23 /dev/null\n')

元の回答:

Envoy を試すことをお勧めします。これはサブプロセスのラッパーです。これは、 置換するエイム 古いモジュールと関数です。 Envoyは人間のサブプロセスです。

readme の使用例

>>> r = envoy.run('git config', data='data to pipe in', timeout=2)

>>> r.status_code
129
>>> r.std_out
'usage: git config [options]'
>>> r.std_err
''

パイプも周りに:

>>> r = envoy.run('uptime | pbcopy')

>>> r.command
'pbcopy'
>>> r.status_code
0

>>> r.history
[<Response 'uptime'>]
45
Joe

これが私のコマンドの実行方法です。このコードには、必要なものがすべて揃っています

from subprocess import Popen, PIPE
cmd = "ls -l ~/"
p = Popen(cmd , Shell=True, stdout=PIPE, stderr=PIPE)
out, err = p.communicate()
print "Return code: ", p.returncode
print out.rstrip(), err.rstrip()
45
Usman Khan

結果の出力なし

import os
os.system("your command here")

結果を出力すると:

import commands
commands.getoutput("your command here")
or
commands.getstatusoutput("your command here")
34
Zuckonit

https://docs.python.org/2/library/subprocess.html

...または非常に単純なコマンドの場合

import os
os.system('cat testfile')
28
Ben Hoffstein

Plumbum もあります

>>> from plumbum import local
>>> ls = local["ls"]
>>> ls
LocalCommand(<LocalPath /bin/ls>)
>>> ls()
u'build.py\ndist\ndocs\nLICENSE\nplumbum\nREADME.rst\nsetup.py\ntests\ntodo.txt\n'
>>> notepad = local["c:\\windows\\notepad.exe"]
>>> notepad()                                   # Notepad window pops up
u''                                             # Notepad window is closed by user, command returns
27
stuckintheshuck

os.systemは問題ありませんが、古いものです。それはあまり安全でもありません。代わりにsubprocessを試してください。 subprocessはshを直接呼び出さないため、os.systemよりも安全です。

より多くの情報を入手しなさい ここ

27
Martin W

Pythonで外部コマンドを呼び出す

簡単です。CompletedProcessオブジェクトを返すsubprocess.runを使用します。

>>> import subprocess
>>> completed_process = subprocess.run('python --version')
Python 3.6.1 :: Anaconda 4.4.0 (64-bit)
>>> completed_process
CompletedProcess(args='python --version', returncode=0)

どうして?

Python 3.5以降、ドキュメントは subprocess.run を推奨しています。

サブプロセスを呼び出すための推奨される方法は、それが処理できるすべてのユースケースに対してrun()関数を使用することです。より高度な使用例では、基礎となるPopenインターフェースを直接使用できます。

これが最も簡単な使用法の例です - そして、それはまさに尋ねられたようにします:

>>> import subprocess
>>> completed_process = subprocess.run('python --version')
Python 3.6.1 :: Anaconda 4.4.0 (64-bit)
>>> completed_process
CompletedProcess(args='python --version', returncode=0)

runはコマンドが正常に終了するのを待ってからCompletedProcessオブジェクトを返します。代わりにTimeoutExpiredtimeout=引数を与えた場合)またはCalledProcessError(失敗してcheck=Trueを渡した場合)が発生する可能性があります。

上記の例から推測できるように、stdoutとstderrはどちらもデフォルトであなた自身のstdoutとstderrにパイプされます。

返されたオブジェクトを調べて、与えられたコマンドとreturncodeを見ることができます。

>>> completed_process.args
'python --version'
>>> completed_process.returncode
0

出力を取り込む

出力をキャプチャしたい場合は、適切なstderrまたはstdoutsubprocess.PIPEを渡すことができます。

>>> cp = subprocess.run('python --version', 
                        stderr=subprocess.PIPE, 
                        stdout=subprocess.PIPE)
>>> cp.stderr
b'Python 3.6.1 :: Anaconda 4.4.0 (64-bit)\r\n'
>>> cp.stdout
b''

(バージョン情報が標準出力ではなく標準エラー出力に出力されるのは、面白くて直感に反すると思います。)

コマンドリストを渡す

(質問が示唆するように)手動でコマンド文字列を提供することから、プログラムで構築された文字列を提供することへと容易に移行するかもしれません。 文字列をプログラム的に構築しません。 これは潜在的なセキュリティ問題です。入力を信頼していないと仮定することをお勧めします。 

>>> import textwrap
>>> args = ['python', textwrap.__file__]
>>> cp = subprocess.run(args, stdout=subprocess.PIPE)
>>> cp.stdout
b'Hello there.\r\n  This is indented.\r\n'

注意してください、argsだけ位置的に渡されるべきです。

フルサイン

これがソースの実際の署名であり、help(run)で示されています。

def run(*popenargs, input=None, timeout=None, check=False, **kwargs):

popenargskwargsPopenコンストラクタに渡されます。 inputは、サブプロセスの標準入力にパイプされるバイトの文字列(またはencodingまたはuniversal_newlines=Trueが指定されている場合はUnicode)にすることができます。

ドキュメントには、timeout=check=Trueの説明があります。

Timeout引数はPopen.communicate()に渡されます。タイムアウトが期限切れになると、子プロセスは強制終了されて待機します。 TimeoutExpired例外は、子プロセスが終了した後で再度発生します。

チェックが真で、プロセスがゼロ以外の終了コードで終了した場合、 CalledProcessError例外が発生します。その例外の属性は、引数、終了コード、およびそれらがキャプチャされた場合はstdoutとstderrを保持します。

そしてcheck=Trueのこの例は、私が思いつくものよりも優れています。

>>> subprocess.run("exit 1", Shell=True, check=True)
Traceback (most recent call last):
  ...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1

拡張署名

ドキュメントで与えられているように、これは拡張された署名です。

subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, 
Shell=False, cwd=None, timeout=None, check=False, encoding=None, 
errors=None)

これはargsリストだけが位置的に渡されるべきであることを示していることに注意してください。そのため、残りの引数をキーワード引数として渡します。

ポペン

代わりにPopenを使うときは?私は議論だけでユースケースを見つけるのに苦労するでしょう。ただし、Popenを直接使用すると、poll、 'send_signal'、 'terminate'、 'wait'などのメソッドにアクセスできます。

これは ソース で与えられているPopenシグネチャです。これは情報の最も正確なカプセル化であると思います(help(Popen)とは対照的に)。

def __init__(self, args, bufsize=-1, executable=None,
             stdin=None, stdout=None, stderr=None,
             preexec_fn=None, close_fds=_PLATFORM_DEFAULT_CLOSE_FDS,
             Shell=False, cwd=None, env=None, universal_newlines=False,
             startupinfo=None, creationflags=0,
             restore_signals=True, start_new_session=False,
             pass_fds=(), *, encoding=None, errors=None):

しかしもっと有益な情報は Popenのドキュメント

subprocess.Popen(args, bufsize=-1, executable=None, stdin=None,
                 stdout=None, stderr=None, preexec_fn=None, close_fds=True,
                 Shell=False, cwd=None, env=None, universal_newlines=False,
                 startupinfo=None, creationflags=0, restore_signals=True,
                 start_new_session=False, pass_fds=(), *, encoding=None, errors=None)

新しいプロセスで子プログラムを実行します。 POSIXでは、クラスは子プログラムを実行するために os.execvp()のような動作を使用します。 Windowsでは、クラスはWindowsのCreateProcess()関数を使用します。 Popenへの議論は以下の通りです。

Popenに関する残りのドキュメントを理解することは読者のための課題として残されるでしょう。

24
Aaron Hall

これは簡単です。

import os
cmd = "your command"
os.system(cmd)
23

つかいます:

import os

cmd = 'ls -al'

os.system(cmd)

os - このモジュールは、オペレーティングシステムに依存する機能を使用するための移植性のある方法を提供します。

より多くのos関数については、 here がドキュメントです。

23
Priyankara

戻り値をテストしたくない場合はsubprocess.check_callが便利です。エラーが発生すると例外がスローされます。

19
cdunn2001

私は サブプロセスshlex と一緒に使う傾向があります(引用符付き文字列のエスケープを処理するため)

>>> import subprocess, shlex
>>> command = 'ls -l "/your/path/with spaces/"'
>>> call_params = shlex.split(command)
>>> print call_params
["ls", "-l", "/your/path/with spaces/"]
>>> subprocess.call(call_params)
18
Emil Stenström

os.systemは結果を保存することを許可していませんので、結果を何らかのリストに保存したい場合やsubprocess.callが機能するものであれば。

17
Saurabh Bangad

ここにはもう1つ違いがありますが、これについては前述していません。

subprocess.Popenは<command>をサブプロセスとして実行します。私の場合は、他のプログラム<b>と通信する必要があるファイル<a>を実行する必要があります。 

サブプロセスを試しましたが、実行は成功しました。ただし、<b>は<a>と通信できませんでした。端末から両方を実行した場合、すべて正常です。

もう1つ:(注:kwriteは他のアプリケーションとは動作が異なります。Firefoxで以下を試しても結果は同じにはなりません。)

os.system("kwrite")を試すと、ユーザーがkwriteを閉じるまでプログラムフローはフリーズします。それを克服するために私は代わりにos.system(konsole -e kwrite)を試しました。今回はプログラムは流れ続けました、しかしkwriteはコンソールのサブプロセスになりました。

誰もがサブプロセスではないkwriteを実行します(つまり、システムモニタでは、ツリーの左端のEdgeに表示される必要があります)。

17
Atinc Delican

私は Shell_command がとても簡単です。これはサブプロセスモジュールの上に構築されています。

これはdocsからの例です:

>>> from Shell_command import Shell_call
>>> Shell_call("ls *.py")
setup.py  Shell_command.py  test_Shell_command.py
0
>>> Shell_call("ls -l *.py")
-rw-r--r-- 1 ncoghlan ncoghlan  391 2011-12-11 12:07 setup.py
-rw-r--r-- 1 ncoghlan ncoghlan 7855 2011-12-11 16:16 Shell_command.py
-rwxr-xr-x 1 ncoghlan ncoghlan 8463 2011-12-11 16:17 test_Shell_command.py
0
16
mdwhatcott

osモジュールを使う

import os
os.system("your command")

例えば

import os
os.system("ifconfig")
15
abhi krishnan

恥知らずなプラグ、私はこれのためにライブラリを書きました:P https://github.com/houqp/Shell.py

基本的にはpopenとshlexのラッパーです。パイピングコマンドもサポートしているので、Pythonでコマンドを簡単にチェーニングできます。だからあなたは以下のようなことをすることができます:

ex('echo hello Shell.py') | "awk '{print $2}'"
14
houqp

Linuxでは、単独で実行する(pythonスクリプトが終了した後も実行を継続する)外部コマンドを呼び出したい場合は、 task spooler または at コマンドとして単純なキューを使用できます。

タスクスプーラの例

import os
os.system('ts <your-command>')

タスクスプーラに関する注意事項(ts) 

  1. 次のようにして、実行する同時プロセス数( "スロット")を設定できます。

    ts -S <number-of-slots>

  2. tsをインストールするのに管理者権限は必要ありません。単純なmakeを使ってソースからそれをダウンロードしてコンパイルし、それをあなたのパスに追加すれば完了です。

14
Yuval Atzmon

あなたはPopenを使うことができ、それから手続きの状態をチェックすることができます。

from subprocess import Popen

proc = Popen(['ls', '-l'])
if proc.poll() is None:
    proc.kill()

subprocess.Popen をチェックしてください。

13
admire

Windowsでは、subprocessモジュールをインポートして、以下のようにsubprocess.Popen()subprocess.Popen().communicate()およびsubprocess.Popen().wait()を呼び出すことによって外部コマンドを実行することができます。

# Python script to run a command line
import subprocess

def execute(cmd):
    """
        Purpose  : To execute a command and return exit status
        Argument : cmd - command to execute
        Return   : exit_code
    """
    process = subprocess.Popen(cmd, Shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    (result, error) = process.communicate()

    rc = process.wait()

    if rc != 0:
        print "Error: failed to execute command:", cmd
        print error
    return result
# def

command = "tasklist | grep python"
print "This process detail: \n", execute(command)

出力:

This process detail:
python.exe                     604 RDP-Tcp#0                  4      5,660 K
12
Swadhikar C

コマンドを実行して結果を取得するための最も簡単な方法:

from commands import getstatusoutput

try:
    return getstatusoutput("ls -ltr")
except Exception, e:
    return None
11
Garfield

Openstack neutronからネットワークIDを取得するには

#!/usr/bin/python
import os
netid= "nova net-list | awk '/ External / { print $2 }'"
temp=os.popen(netid).read()  /* here temp also contains new line (\n) */
networkId=temp.rstrip()
print(networkId)

nova net-list の出力

+--------------------------------------+------------+------+
| ID                                   | Label      | CIDR |
+--------------------------------------+------------+------+
| 431c9014-5b5d-4b51-a357-66020ffbb123 | test1      | None |
| 27a74fcd-37c0-4789-9414-9531b7e3f126 | External   | None |
| 5a2712e9-70dc-4b0e-9281-17e02f4684c9 | management | None |
| 7aa697f5-0e60-4c15-b4cc-9cb659698512 | Internal   | None |
+--------------------------------------+------------+------+

print(networkId) の出力

27a74fcd-37c0-4789-9414-9531b7e3f126
11
IRSHAD

ここに私の2セントがあります:私の考えでは、これは外部コマンドを扱うときのベストプラクティスです...

これらはexecuteメソッドからの戻り値です...

pass, stdout, stderr = execute(["ls","-la"],"/home/user/desktop")

これはexecuteメソッドです...

def execute(cmdArray,workingDir):

    stdout = ''
    stderr = ''

    try:
        try:
            process = subprocess.Popen(cmdArray,cwd=workingDir, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=1)
        except OSError:
            return [False, '', 'ERROR : command(' + ' '.join(cmdArray) + ') could not get executed!']

        for line in iter(process.stdout.readline, b''):

            try:
                echoLine = line.decode("utf-8")
            except:
                echoLine = str(line)

            stdout += echoLine

        for line in iter(process.stderr.readline, b''):

            try:
                echoLine = line.decode("utf-8")
            except:
                echoLine = str(line)

            stderr += echoLine

    except (KeyboardInterrupt,SystemExit) as err:
        return [False,'',str(err)]

    process.stdout.close()

    returnCode = process.wait()
    if returnCode != 0 or stderr != '':
        return [False, stdout, stderr]
    else:
        return [True, stdout, stderr]
10
Uroš Jarc

呼び出しはPython(2.7および3.4​​以降)のタスク実行ツールおよびライブラリです。これはシェルコマンドを実行するためのクリーンでハイレベルなAPIを提供します。

>>> from invoke import run
>>> cmd = "pip install -r requirements.txt"
>>> result = run(cmd, hide=True, warn=True)
>>> print(result.ok)
True
>>> print(result.stdout.splitlines()[-1])
Successfully installed invocations-0.13.0 pep8-1.5.7 spec-1.3.1
8
Valery Ramusik

これは外部コマンドを呼び出してコマンドの出力を返すか出力するものです。

Python サブプロセス check_outputはに適しています

引数を指定してcommandを実行し、その出力をバイト文字列として返します。

import subprocess
proc = subprocess.check_output('ipconfig /all')
print proc
7
Rajiv Sharma

つかいます:

import subprocess

p = subprocess.Popen("df -h", Shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]
print p.split("\n")

これは、より扱いやすいNice出力を提供します。

['Filesystem      Size  Used Avail Use% Mounted on',
 '/dev/sda6        32G   21G   11G  67% /',
 'none            4.0K     0  4.0K   0% /sys/fs/cgroup',
 'udev            1.9G  4.0K  1.9G   1% /dev',
 'tmpfs           387M  1.4M  386M   1% /run',
 'none            5.0M     0  5.0M   0% /run/lock',
 'none            1.9G   58M  1.9G   3% /run/shm',
 'none            100M   32K  100M   1% /run/user',
 '/dev/sda5       340G  222G  100G  69% /home',
 '']
7
David Okwii

議論を追加するために、Pythonコンソールを使用する場合は、 IPython から外部コマンドを呼び出すことができます。 IPythonのプロンプトでは、 '!'を前に付けることでシェルコマンドを呼び出すことができます。 Pythonコードとシェルを組み合わせて、シェルスクリプトの出力をPython変数に割り当てることもできます。

例えば:

In [9]: mylist = !ls

In [10]: mylist
Out[10]:
['file1',
 'file2',
 'file3',]
7
imagineerThat

Pythonで外部コマンドを呼び出す

外部コマンドを呼び出す簡単な方法はos.system(...)を使うことです。そしてこの関数はコマンドの終了値を返します。しかし、欠点は標準出力や標準エラー出力が出ないことです。

ret = os.system('some_cmd.sh')
if ret != 0 :
    print 'some_cmd.sh execution returned failure'

バックグラウンドでPythonの外部コマンドを呼び出す

subprocess.Popenは、os.systemを使用するよりも外部コマンドを実行するためのより高い柔軟性を提供します。バックグラウンドでコマンドを開始し、それが終了するのを待つことができます。そしてその後、標準出力と標準エラー出力を得ることができます。

proc = subprocess.Popen(["./some_cmd.sh"], stdout=subprocess.PIPE)
print 'waiting for ' + str(proc.pid)
proc.wait()
print 'some_cmd.sh execution finished'
(out, err) = proc.communicate()
print 'some_cmd.sh output : ' + out

バックグラウンドでPythonで長時間実行されている外部コマンドを呼び出し、しばらくすると停止します

subprocess.Popenを使用してバックグラウンドで長時間実行されているプロセスを開始し、そのタスクが完了したらしばらくしてから強制終了することもできます。

proc = subprocess.Popen(["./some_long_run_cmd.sh"], stdout=subprocess.PIPE)
# Do something else
# Now some_long_run_cmd.sh exeuction is no longer needed, so kill it
os.system('kill -15 ' + str(proc.pid))
print 'Output : ' proc.communicate()[0]
6
rashok

Pythonで外部コマンドを実行するにはさまざまな方法があり[]、それらすべてに独自の長所と短所があります。

私の同僚と私はPythonのシステム管理ツールを書いてきたので、私たちはたくさんの外部コマンドを実行する必要があります、そして時々あなたはそれらをブロックまたは非同期に実行したいです。

戻りコードやエラーを処理するさまざまな方法もありますそして、あなたは出力を解析し、( expect のようなスタイルで)新しい入力を提供したいかもしれません。あるいは、stdin、stdout、およびstderrを別のttyで実行するようにリダイレクトする必要があります(たとえばscreenを使用している場合)。

ですから、おそらく外部コマンドの周りにたくさんのラッパーを書かなければならないでしょう。だからここに私たちが書いたPythonモジュールがあります。あなたが望むほとんどすべてのものを扱うことができます。

https://github.com/hpcugent/vsc-base/blob/master/lib/vsc/utils/run.py

6
Jens Timmerman

例として(Linuxの場合):

import subprocess
subprocess.run('mkdir test.dir', Shell=True)

現在のディレクトリにtest.dirが作成されます。これもうまくいくことに注意してください。

import subprocess
subprocess.call('mkdir test.dir', Shell=True)

Os.systemを使用した同等のコードは次のとおりです。

import os
os.system('mkdir test.dir')

ベストプラクティスは、osの代わりにサブプロセスを使用し、.cunよりも.runを優先することです。 サブプロセスについて知る必要があるのは、 here だけです。また、すべてのPythonドキュメントは here からダウンロードできます。 .zipとして圧縮されたPDFをダウンロードしました。これは、tutorial.pdf(81ページ)にosモジュールの概要がまとめられているためです。その上、それはPythonコーダーのための権威あるリソースです。

6
user8468899

Python 3.5以降の場合、 サブプロセスモジュールから関数を実行 を使用することをお勧めします。これはCompletedProcessオブジェクトを返し、そこから戻りコードだけでなく出力も簡単に取得できます。

from subprocess import PIPE, run

command = ['echo', 'hello']
result = run(command, stdout=PIPE, stderr=PIPE, universal_newlines=True)
print(result.returncode, result.stdout, result.stderr)
5

多くの場合、私は以下の関数を外部コマンドに使用します、そしてこれは長期実行プロセスのために特に便利です。以下のメソッド[{プロセス出力のテール/が実行中で出力を返す場合、プロセスが失敗すると例外が発生します.

プロセスがプロセスのpoll()メソッド _を使用して実行された場合に発生します。

import subprocess,sys

def exec_long_running_proc(command, args):
    cmd = "{} {}".format(command, " ".join(str(arg) if ' ' not in arg else arg.replace(' ','\ ') for arg in args))
    print(cmd)
    process = subprocess.Popen(cmd, Shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

    # Poll process for new output until finished
    while True:
        nextline = process.stdout.readline().decode('UTF-8')
        if nextline == '' and process.poll() is not None:
            break
        sys.stdout.write(nextline)
        sys.stdout.flush()

    output = process.communicate()[0]
    exitCode = process.returncode

    if (exitCode == 0):
        return output
    else:
        raise Exception(command, exitCode, output)

あなたはこのようにそれを呼び出すことができます:

exec_long_running_proc(command = "Hive", args=["-f", hql_path])
5
am5

簡単な方法はosモジュールを使うことです:

import os
os.system('ls')

あるいは、サブプロセスモジュールを使用することもできます。

import subprocess
subprocess.check_call('ls')

結果を変数に格納したい場合は、次のようにしてください。

import subprocess
r = subprocess.check_output('ls')
4
amehta

subprocess.call :を使用してください。

from subprocess import call

# using list
call(["echo", "Hello", "world"])

# single string argument varies across platforms so better split it
call("echo Hello world".split(" "))
4
andruso

Popen Pythonモジュールのsubprocess関数を使用するのが、Linuxコマンドを実行するための最も簡単な方法です。その中で、Popen.communicate()関数はあなたのコマンド出力を与えるでしょう。例えば

import subprocess

..
process = subprocess.Popen(..)   # Pass command and arguments to the function
stdout, stderr = process.communicate()   # Get command output and error
..
4
Asif Hasnain

コマンドを呼び出すには多くの方法があります。

  • 例えば:

and.exeに2つのパラメーターが必要な場合。 cmdでは、sample.exeを呼び出すことができます:and.exe 2 3を使用して、画面に5を表示します。

Pythonスクリプトを使用してand.exeを呼び出す場合、次のようにする必要があります。

  1. os.system(cmd,...)

    • os.system(("and.exe" + " " + "2" + " " + "3"))
  2. os.popen(cmd,...)

    • os.popen(("and.exe" + " " + "2" + " " + "3"))
  3. subprocess.Popen(cmd,...)
    • subprocess.Popen(("and.exe" + " " + "2" + " " + "3"))

難しすぎるので、cmdをスペースで結合できます。

import os
cmd = " ".join(exename,parameters)
os.popen(cmd)
4
liuyip

Pythonのノートブック( Jupyter 、Zeppelin、Databricks、またはGoogle Cloud Datalabなど)からシェルコマンドを呼び出す必要がある場合は、!プレフィックスを使用することができます。

例えば、

!ls -ilF
3
dportman

私はこのユースケースを手助けするために小さなライブラリを書きました:

https://pypi.org/project/citizenshell/

それを使用してインストールすることができます 

pip install citizenshell

そして、次のように使われます。

from citizenshell import sh
assert sh("echo Hello World") == "Hello World"

次のように標準出力を標準エラー出力から分離して終了コードを抽出できます。

result = sh(">&2 echo error && echo output && exit 13")
assert result.stdout() == ["output"]
assert result.stderr() == ["error"]
assert result.exit_code() == 13

そして素晴らしいことは、出力の処理を開始する前に基礎となるシェルが終了するのを待つ必要がないということです。

for line in sh("for i in 1 2 3 4; do echo -n 'It is '; date +%H:%M:%S; sleep 1; done", wait=False)
    print ">>>", line + "!"

wait = Falseのおかげで、利用可能な行を印刷します。

>>> It is 14:24:52!
>>> It is 14:24:53!
>>> It is 14:24:54!
>>> It is 14:24:55!

より多くの例が https://github.com/meuter/citizenshell にあります。

3
Cédric

Pythonを使ってシェルコマンドを実行する方法は2つあります。下記の例はどちらもPythonを使って現在の作業ディレクトリの名前(pwd)を取得する方法を示しています。 pwdの代わりに他のUnixコマンドを使用することができます。 

1.> 1番目の方法: pythonの os モジュール、そしてそこから system() 関数を使ってPythonでシェルコマンドを実行することができます。

import os
os.system('pwd')

出力:

/Users/siddharth

1.>> 2番目の方法: 別の方法は サブプロセス moduleと call() 関数を使うことです。 

import subprocess
subprocess.call('pwd')

出力:

/Users/siddharth
3

私は次のメソッド 'run'をお勧めします。これはSTDOUT、STDERR、および終了ステータスを辞書として取得するのに役立ちます。この呼び出し側は、 'run'メソッドによって返された辞書を読んで、プロセスの実際の状態を知ることができます。 

  def run (cmd):
       print "+ DEBUG exec({0})".format(cmd)
       p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, Shell=True)
       (out, err) = p.communicate()
       ret        = p.wait()
       out        = filter(None, out.split('\n'))
       err        = filter(None, err.split('\n'))
       ret        = True if ret == 0 else False
       return dict({'output': out, 'error': err, 'status': ret})
  #end
2
Viswesn

いくつかの調査の後、私は私のために非常にうまくいく以下のコードを持っています。基本的には標準出力と標準エラー出力の両方をリアルタイムで表示します。それがそれを必要とする他の誰かに役立つことを願っています。

stdout_result = 1
stderr_result = 1


def stdout_thread(pipe):
    global stdout_result
    while True:
        out = pipe.stdout.read(1)
        stdout_result = pipe.poll()
        if out == '' and stdout_result is not None:
            break

        if out != '':
            sys.stdout.write(out)
            sys.stdout.flush()


def stderr_thread(pipe):
    global stderr_result
    while True:
        err = pipe.stderr.read(1)
        stderr_result = pipe.poll()
        if err == '' and stderr_result is not None:
            break

        if err != '':
            sys.stdout.write(err)
            sys.stdout.flush()


def exec_command(command, cwd=None):
    if cwd is not None:
        print '[' + ' '.join(command) + '] in ' + cwd
    else:
        print '[' + ' '.join(command) + ']'

    p = subprocess.Popen(
        command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd
    )

    out_thread = threading.Thread(name='stdout_thread', target=stdout_thread, args=(p,))
    err_thread = threading.Thread(name='stderr_thread', target=stderr_thread, args=(p,))

    err_thread.start()
    out_thread.start()

    out_thread.join()
    err_thread.join()

    return stdout_result + stderr_result
2
Jake W

Sultan は、この目的のための最近のパッケージです。ユーザー特権の管理と役立つエラーメッセージの追加に関するいくつかの便利な機能を提供します。

from sultan.api import Sultan

with Sultan.load(Sudo=True, hostname="myserver.com") as sultan:
  sultan.yum("install -y tree").run()
1
Zach Valenta

私はエラーを処理し、出力や他のものをリダイレクトするためのラッパーを書きました。

import shlex
import psutil
import subprocess

def call_cmd(cmd, stdout=sys.stdout, quiet=False, Shell=False, raise_exceptions=True, use_shlex=True, timeout=None):
    """Exec command by command line like 'ln -ls "/var/log"'
    """
    if not quiet:
        print("Run %s", str(cmd))
    if use_shlex and isinstance(cmd, (str, unicode)):
        cmd = shlex.split(cmd)
    if timeout is None:
        process = subprocess.Popen(cmd, stdout=stdout, stderr=sys.stderr, Shell=shell)
        retcode = process.wait()
    else:
        process = subprocess.Popen(cmd, stdout=stdout, stderr=sys.stderr, Shell=shell)
        p = psutil.Process(process.pid)
        finish, alive = psutil.wait_procs([p], timeout)
        if len(alive) > 0:
            ps = p.children()
            ps.insert(0, p)
            print('waiting for timeout again due to child process check')
            finish, alive = psutil.wait_procs(ps, 0)
        if len(alive) > 0:
            print('process {} will be killed'.format([p.pid for p in alive]))
            for p in alive:
                p.kill()
            if raise_exceptions:
                print('External program timeout at {} {}'.format(timeout, cmd))
                raise CalledProcessTimeout(1, cmd)
        retcode = process.wait()
    if retcode and raise_exceptions:
        print("External program failed %s", str(cmd))
        raise subprocess.CalledProcessError(retcode, cmd)

このように呼ぶことができます:

cmd = 'ln -ls "/var/log"'
stdout = 'out.txt'
call_cmd(cmd, stdout)
1
Asav Patel

Eliによって前述された サブプロセスモジュール は非常に強力ですが、不正な標準システムコールを作成してその出力を検査するための構文は不必要に冗長です。

システムコールを行う最も簡単な方法は commandsモジュール を使うことです(Linuxのみ)。

> import commands
> commands.getstatusoutput("grep matter alice-in-wonderland.txt")
(0, "'Then it doesn't matter which way you go,' said the Cat.")

タプルの最初の項目はプロセスのリターンコードです。 2番目の項目はその標準出力(および標準エラー、マージ済み)です。


Python開発者はcommandsモジュールを「非推奨」にしましたが、それはあなたがそれを使うべきではないという意味ではありません。彼らがもうそれを開発していないということだけ、それは大丈夫です、なぜならそれは(その小さいながらも重要な機能において)完全であるからです。

1
Colonel Panic

いくつかの答えは以前のバージョンのpythonに関連していたかos.systemモジュールを使用していたので、私は私のようなpython 3.5+subprocessを使用するつもりの人にこの答えを投稿します。 Linuxで私にとって次のことがうまくいきました。

import subprocess

#subprocess.run() returns a completed process object that can be inspected
c = subprocess.run(["ls", "-ltrh"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print(c.stdout.decode('utf-8'))

ドキュメンテーション で述べられているように、PIPE値はバイトシーケンスであり、それらを適切に示すためにはデコードが考慮されるべきです。それ以降のバージョンのpythonでは、 subprocess.run() のkwargsにtext=Trueおよびencoding='utf-8'が追加されています。 

上記のコードの出力は次のとおりです。

total 113M
-rwxr-xr-x  1 farzad farzad  307 Jan 15  2018 vpnscript
-rwxrwxr-x  1 farzad farzad  204 Jan 15  2018 ex
drwxrwxr-x  4 farzad farzad 4.0K Jan 22  2018 scripts
.... # some other lines
1
Farzad Vertigo

subprocess.getoutput()subprocess.getstatusutput()を使用することもできます。これらは、非推奨のcommandsモジュールからのレガシーシェル呼び出し関数です。 :

subprocess.getstatusoutput(cmd)

シェルでexitcodeを実行した(outputcmd)を返します。


subprocess.getoutput(cmd)

シェルでstdoutを実行した場合の出力(stderrおよびcmd)を返します。

0
Pedro Lobito

importを使用してから、ファイル名を使用できます。たとえば、組み込みモジュール「ランダム」を使用する場合:import random

0
Chris Oliver

あなたが _ではなく_ コマンドでユーザ入力を使っているなら、これを使うことができます。

from os import getcwd
from subprocess import check_output
from shlex import quote

def sh(command):
    return check_output(quote(command), Shell=True, cwd=getcwd(), universal_newlines=True).strip()

そしてそれを使う

branch = sh('git rev-parse --abbrev-ref HEAD') 

Shell=Trueはシェルを生成するので、あなたはパイプとそのようなシェルのものを使うことができますsh('ps aux | grep python')。これは、ハードコードされたコマンドを実行し、その出力を処理するために非常に便利です。 universal_lines=Trueは、出力がバイナリではなく文字列で返されることを確認します。

cwd=getcwd()は、コマンドがインタプリタと同じ作業ディレクトリで実行されることを確認します。これはgitコマンドが上のgitブランチ名の例のように動作するのに便利です。

いくつかのレシピ

  • 空きメモリー(メガバイト):sh('free -m').split('\n')[1].split()[1]
  • パーセントsh('df -m /').split('\n')[1].split()[4][0:-1]上/上の空き容量
  • cpu load sum(map(float, sh('ps -ef -o pcpu').split('\n')[1:])

しかし、これはドキュメントからのユーザー入力にとって安全ではありません:

セキュリティ上の考慮事項¶

他のpopen関数とは異なり、この実装は暗黙的にシステムシェルを呼び出すことは決してありません。これは、シェルのメタ文字を含むすべての文字を安全に子プロセスに渡すことができることを意味します。 Shell = Trueを介してシェルが明示的に呼び出された場合、シェルインジェクションの脆弱性を回避するためにすべての空白文字とメタ文字が適切に引用符で囲まれていることを確認するのはアプリケーションの責任です。

Shell = Trueを使用する場合、shlex.quote()関数を使用して、シェルコマンドの構築に使用される文字列内の空白文字とシェルメタ文字を正しくエスケープすることができます。

shlex.quote()を使用しても、シェルコマンドでユーザー入力を使用するときにちょっと妄想を保つのに良いです。 1つの選択肢は、ハードコードコマンドを使用して一般的な出力を取得し、ユーザー入力でフィルタリングすることです。とにかくShell=Falseを使うことはあなたが実行したい正確なプロセスだけが実行されることを確実にするでしょう、あるいはあなたはNo such file or directoryエラーを得るでしょう。

また、Shell=Trueにはパフォーマンスへの影響がいくらかあります。私のテストによると、Shell=False(デフォルト)よりも約20%遅くなります。

In [50]: timeit("check_output('ls -l'.split(), universal_newlines=True)", number=1000, globals=globals())
Out[50]: 2.6801227919995654

In [51]: timeit("check_output('ls -l', universal_newlines=True, Shell=True)", number=1000, globals=globals())
Out[51]: 3.243950183999914
0
geckos

Pythonシェルスクリプトを記述していて、システムにIPythonがインストールされている場合、bang magicを使用してIPython内でコマンドを実行できます。

!ls
filelist = !ls
0