Pythonスクリプト内から外部コマンドを呼び出す方法(UnixシェルまたはWindowsコマンドプロンプトで入力した場合と同様)
Pythonスクリプト内から外部コマンドを呼び出す方法(UnixシェルまたはWindowsコマンドプロンプトで入力した場合と同様)
回答:
標準ライブラリのサブプロセスモジュールを見てください。
import subprocess
subprocess.run(["ls", "-l"])
利点subprocess
対は、system
それは(あなたが得ることができ、より柔軟であることであるstdout
、stderr
「本物の」ステータスコード、より良いエラー処理、等...)。
公式ドキュメントは推奨していますsubprocess
代替の上にモジュールをos.system()
:
この
subprocess
モジュールは、新しいプロセスを生成してその結果を取得するためのより強力な機能を提供します。この関数を使用するよりも、そのモジュールを使用することをお勧めします[os.system()
]。
サブプロセスモジュールと交換古い関数内のセクションsubprocess
のドキュメントは、いくつかの有用なレシピを有することができます。
3.5より前のバージョンのPythonでは、次を使用しますcall
。
import subprocess
subprocess.call(["ls", "-l"])
shell=True
。
shell=True
Pythonにはos.path.expandvarsが付属しているため、使用しないでください。あなたのケースでは次のように記述することができますos.path.expandvars("$PATH")
。@SethMMortonはコメントを再検討してください-> shell = Trueを使用しないのはなぜですか
for
ループで複数のコマンドを実行したい場合、pythonスクリプトをブロックせずにそれを行うにはどうすればよいですか?たくさん実行したいコマンドの出力は気にしません。
subprocess
場合はshell=False
、when で使用できるリストを使用shlex.split
して、これを行う簡単な方法としてdocs.python.org/2/library/shlex.html#shlex.split
外部プログラムを呼び出す方法の概要と、それぞれの長所と短所を次に示します。
os.system("some_command with args")
コマンドと引数をシステムのシェルに渡します。この方法で実際に一度に複数のコマンドを実行し、パイプと入出力リダイレクトを設定できるので、これは素晴らしいことです。例えば:
os.system("some_command < input_file | another_command > output_file")
ただし、これは便利ですが、スペースなどのシェル文字のエスケープを手動で処理する必要があります。一方、これにより、単にシェルコマンドであり、実際には外部プログラムではないコマンドを実行することもできます。ドキュメントを参照してください。
stream = os.popen("some_command with args")
と同じことを行いos.system
ますが、そのプロセスの標準入出力にアクセスするために使用できるファイルのようなオブジェクトを提供します。popenには他にも3つのバリエーションがあり、すべてがわずかに異なる方法でI / Oを処理します。すべてを文字列として渡すと、コマンドはシェルに渡されます。それらをリストとして渡すと、何かをエスケープすることを心配する必要はありません。ドキュメントを参照してください。
モジュールの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つの統合クラスにすべてのオプションを含めると便利です。ドキュメントを参照してください。
モジュールcall
からの関数subprocess
。これは基本的にPopen
クラスと同じで、すべて同じ引数を取りますが、コマンドが完了して戻りコードが返されるまで待つだけです。例えば:
return_code = subprocess.call("echo Hello World", shell=True)
ドキュメントを参照してください。
Python 3.5以降を使用している場合は、新しいsubprocess.run
関数を使用できます。これは、上記とよく似ていますが、さらに柔軟性が高くCompletedProcess
、コマンドの実行が完了するとオブジェクトを返します。
osモジュールには、Cプログラムにあるすべてのfork / exec / spawn関数もありますが、直接使用することはお勧めしません。
subprocess
モジュールは、おそらくあなたが使用しているものでなければなりません。
最後に、シェルが文字列として実行する最後のコマンドを渡すすべてのメソッドで、エスケープする必要があることに注意してください。渡す文字列の一部が完全に信頼できない場合、セキュリティに深刻な影響があります。たとえば、ユーザーが文字列の一部/任意の部分を入力している場合。不明な場合は、これらのメソッドを定数でのみ使用してください。影響のヒントを与えるには、次のコードを検討してください。
print subprocess.Popen("echo %s " % user_input, stdout=PIPE).stdout.read()
そして、ユーザーが「私のママは私を愛していなかった&& rm -rf /」と入力すると、ファイルシステム全体が消去される可能性があります。
open
。
subprocess.run()
いる場合は、を使用します。docs.python.org/3.5/library/subprocess.html#subprocess.run
subprocess.run(..)
、「これはデフォルトでstdoutまたはstderrをキャプチャしません」と正確に何が行われますか。ほのめかす?subprocess.check_output(..)
STDERR についてはどうですか?
echo
渡された文字列の前に注意してPopen
ください。したがって、完全なコマンドはになりますecho my mama didnt love me && rm -rf /
。
subprocess.run()
か、それより古い兄弟などsubprocess.check_call()
。これらでは不十分な場合については、を参照してくださいsubprocess.Popen()
。os.popen()
おそらくまったく言及されるべきではないか、あるいは「あなた自身のfork / exec / spawnコードをハック」した後でさえ来るべきです。
典型的な実装:
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()
。
.readlines()
すべての行を一度に読み取ります。つまり、サブプロセスが終了する(パイプの最後を閉じる)までブロックします。あなたはできる(バッファリングの問題が存在しない場合)、リアルタイムで読み取るには:for line in iter(p.stdout.readline, ''): print line,
p.stdout.readline()
noですs
)。子が多くのデータを生成しない場合、出力はリアルタイムではありません。Qの2番目の理由を参照してください:なぜパイプ(popen())を使用しないのですか?。この回答ではいくつかの回避策が提供されています(pexpect、pty、stdbuf)
Popen
、単純なタスクにはお勧めしません。これも不必要に指定しますshell=True
。subprocess.run()
答えの1つを試してください。
子プロセスを呼び出し側から切り離す(子プロセスをバックグラウンドで開始する)ためのいくつかのヒント。
CGIスクリプトから長いタスクを開始するとします。つまり、子プロセスはCGIスクリプト実行プロセスよりも長く存続する必要があります。
サブプロセスモジュールドキュメントの古典的な例は次のとおりです。
import subprocess
import sys
# Some code here
pid = subprocess.Popen([sys.executable, "longtask.py"]) # Call subprocess
# Some more code here
ここでの考え方は、longtask.pyが終了するまで「call subprocess」の行で待機したくないということです。しかし、例からの「ここにいくつかのより多くのコード」の行の後に何が起こるかは明らかではありません。
私のターゲットプラットフォームはFreeBSDでしたが、開発はWindows上で行われたため、最初にWindowsで問題に直面しました。
Windows(Windows XP)では、longtask.pyが作業を完了するまで、親プロセスは完了しません。これは、CGIスクリプトに必要なものではありません。この問題はPythonに固有のものではありません。PHPコミュニティでも問題は同じです。
解決策は、DETACHED_PROCESS プロセス作成フラグをWindows APIの基になるCreateProcess関数に渡すことです。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では、別の問題があります。親プロセスが終了すると、子プロセスも終了します。そして、それもCGIスクリプトに必要なものではありません。いくつかの実験では、問題はsys.stdoutの共有にあるように見えました。そして実用的な解決策は次のとおりです:
pid = subprocess.Popen([sys.executable, "longtask.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
私は他のプラットフォームでコードをチェックしていませんし、FreeBSDでの動作の理由もわかりません。誰かが知っている場合は、あなたのアイデアを共有してください。Pythonでのバックグラウンドプロセスの開始をググリングしても、まだ何もわかりません。
DETACHED_PROCESS
をcreationflags
回避します。代わりに新しいコンソールが必要な場合は、CREATE_NEW_CONSOLE
(0x00000010)を使用します。
os.devnull
。子プロセスが親プロセスと同時にユーザーと対話するようにする場合は、新しいコンソールを作成します。1つのウィンドウで両方を実行しようとすると混乱を招くでしょう。
import os
os.system("your command")
コマンドはクリーンアップされていないため、これは危険であることに注意してください。「os」モジュールと「sys」モジュールの関連ドキュメントについては、Googleにお任せします。同様のことを行う関数(exec *とspawn *)がたくさんあります。
subprocess
、やや多目的でポータブルなソリューションであることを示しています。もちろん、外部コマンドの実行は本質的に移植性がなく(サポートする必要のあるすべてのアーキテクチャでコマンドが使用可能であることを確認する必要があります)、外部コマンドとしてユーザー入力を渡すことは本質的に安全ではありません。
os.systemの代わりにsubprocessモジュールを使用することをお勧めします。これは、シェルのエスケープが行われるため、はるかに安全だからです。
subprocess.call(['ping', 'localhost'])
subprocess
場合はshell=False
、when で使用できるリストを使用shlex.split
して、これを簡単に行うためにdocs.python.org/2/library/shlex.html#shlex.split(それはドキュメントに応じて推奨される方法ですdocs.python.org/2/library/subprocess.html#popen-constructor)
import os
cmd = 'ls -al'
os.system(cmd)
コマンドの結果を返したい場合は、を使用できますos.popen
。ただし、バージョン2.6以降、サブプロセスモジュールが推奨されるため、これは非推奨です。他の回答でも十分にカバーされています。
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.system
andを使用して外部コマンドを呼び出すこともできますos.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を使用すると、子アプリケーションを生成して制御し、出力からパターンを見つけることができます。これは、Unixでttyを期待するコマンドのサブプロセスのより良い代替手段です。
pexpect.run("ls -l") # Run command as normal
child = pexpect.spawn('scp foo user@example.com:.') # Spawns child application
child.expect('Password:') # When this is the output
child.sendline('mypassword')
ファブリック
ファブリックは、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
ため、Python 3から削除されsubprocess
ました。
この編集は、JFセバスチャンのコメントに基づいています。
私は常に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)
サブプロセスモジュール(Python 3)を使用します。
import subprocess
subprocess.run(['ls', '-l'])
推奨される標準的な方法です。ただし、より複雑なタスク(パイプ、出力、入力など)を作成して作成するのは面倒です。
Pythonバージョンに関する注意:Python 2をまだ使用している場合、subprocess.callは同様の方法で機能します。
ProTipは:shlex.splitは、あなたがのためにコマンドを解析することができrun
、call
およびその他の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
。
呼び出すコマンドからの出力が必要な場合は、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がの
True
場合、指定されたコマンドはシェルを介して実行されます。これは、Pythonを主に拡張制御フローに使用していて、ほとんどのシステムシェルで提供されているにもかかわらず、シェルパイプ、ファイル名のワイルドカード、環境変数の展開、ユーザーの家への〜の展開など、他のシェル機能への便利なアクセスが必要な場合に役立ちます。ディレクトリ。パイソン自体は(特に、多くの貝殻のような機能の実装を提供することをしかし、ノートglob
、fnmatch
、os.walk()
、os.path.expandvars()
、os.path.expanduser()
、およびshutil
)。
check_output
文字列ではなくリストが必要なことに注意してください。引用符で囲まれたスペースに頼らずに呼び出しを有効にする場合、これを行う最も簡単で最も読みやすい方法はsubprocess.check_output("ls -l /dev/null".split())
です。
これがコマンドの実行方法です。このコードには、必要なものがすべて含まれています
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()
subprocess.run
コードが以前のバージョンのPythonとの互換性を維持する必要がない場合は、Python 3.5以降の推奨アプローチです。より一貫性があり、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を試すことをお勧めします。これはサブプロセスのラッパーであり、古いモジュールと関数を置き換えることを目的としています。特使は人間のサブプロセスです。
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'>]
os.system
大丈夫ですが、少し時代遅れです。また、あまり安全ではありません。代わりに、を試してくださいsubprocess
。 subprocess
shを直接呼び出さないため、より安全ですos.system
。
詳細については、こちらをご覧ください。
subprocess
ますが、すべてのセキュリティ問題を削除するわけではなく、独自の厄介な問題があります。
Pythonで外部コマンドを呼び出す
単純なを使用してsubprocess.run
、CompletedProcess
オブジェクトを返します。
>>> 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
オブジェクトを返します。代わりにTimeoutExpired
(timeout=
引数を指定した場合)またはCalledProcessError
(失敗してを渡した場合)が発生する可能性がありますcheck=True
。
上記の例から推測できるように、stdoutとstderrはどちらもデフォルトで独自のstdoutとstderrにパイプされます。
返されたオブジェクトを検査して、指定されたコマンドと戻りコードを確認できます。
>>> completed_process.args
'python --version'
>>> completed_process.returncode
0
出力をキャプチャする場合はsubprocess.PIPE
、適切なstderr
またはに渡すことができますstdout
。
>>> 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''
(バージョン情報がstdoutではなくstderrに入れられるのは興味深いし、少し直観に反しているようです。)
手動でコマンド文字列を提供すること(質問が示唆するように)から、プログラムで構築された文字列を提供することへと簡単に移行できます。プログラムで文字列を構築しないでください。これは潜在的なセキュリティ問題です。入力を信頼していないと想定することをお勧めします。
>>> 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):
popenargs
とkwargs
に与えられるPopen
コンストラクタ。サブプロセスのstdinにパイプされるinput
バイトの文字列(または、encodingまたはを指定する場合はUnicode universal_newlines=True
)にすることができます。
ドキュメントでは説明timeout=
し、check=True
私ができるよりよいです:
タイムアウト引数はPopen.communicate()に渡されます。タイムアウトになると、子プロセスは強制終了され、待機されます。子プロセスが終了した後、TimeoutExpired例外が再度発生します。
チェックがtrueで、プロセスがゼロ以外の終了コードで終了する場合、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):
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
することは、読者のための演習として残します。
shell=True
コマンドをリストとして渡すか、(より良い)リストとして渡す必要があります。
>>> 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
使用する:
import os
cmd = 'ls -al'
os.system(cmd)
os-このモジュールは、オペレーティングシステムに依存する機能を使用するポータブルな方法を提供します。
私はその単純さのためにshell_commandがとても好きです。サブプロセスモジュールの上に構築されています。
ドキュメントの例を次に示します。
>>> 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
ここには、前に述べていない別の違いがあります。
subprocess.Popen
<command>をサブプロセスとして実行します。私の場合、別のプログラム<b>と通信する必要があるファイル<a>を実行する必要があります。
サブプロセスを試してみましたが、実行に成功しました。ただし、<b>は<a>と通信できませんでした。ターミナルから両方を実行すると、すべてが正常です。
もう1つ:(注:kwriteは他のアプリケーションとは動作が異なります。Firefoxで以下を試した場合、結果は同じにはなりません。)
を実行しようとするとos.system("kwrite")
、ユーザーがkwriteを閉じるまでプログラムフローが停止します。それを克服するために代わりに試してみましたos.system(konsole -e kwrite)
。今回はプログラムは流れ続けましたが、kwriteはコンソールのサブプロセスになりました。
誰もがサブプロセスではないkwriteを実行します(つまり、システムモニターでは、ツリーの左端に表示される必要があります)。
恥知らずなプラグ、私はこれのためのライブラリを書いた:P https://github.com/houqp/shell.py
それは基本的に今のところpopenとshlexのラッパーです。また、パイピングコマンドもサポートしているため、Pythonでコマンドを簡単にチェーンできます。したがって、次のようなことができます。
ex('echo hello shell.py') | "awk '{print $2}'"
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
Linuxでは、独立して実行する(Pythonスクリプトの終了後も実行を継続する)外部コマンドを呼び出す場合は、タスクスプーラーまたはatコマンドとして単純なキューを使用できます。
タスクスプーラーの例:
import os
os.system('ts <your-command>')
タスクスプーラーに関する注意事項(ts
):
実行する並行プロセスの数(「スロット」)を次のように設定できます。
ts -S <number-of-slots>
インストールにts
は管理者権限は必要ありません。シンプルなを使用してソースからダウンロードしてコンパイルmake
し、パスに追加すれば完了です。
ts
私が知っているどのディストリビューションでも標準ではありませんが、へのポインタat
は少し便利です。あなたもおそらく言及する必要がありbatch
ます。他の場所と同様に、os.system()
推奨事項では、少なくともそれsubprocess
が推奨される置き換えであることをおそらく言及する必要があります。
Popenを使用して、プロシージャのステータスを確認できます。
from subprocess import Popen
proc = Popen(['ls', '-l'])
if proc.poll() is None:
proc.kill()
subprocess.Popenをチェックしてください。
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
os.popen()
2016年にはお勧めしません。Awkスクリプトは、ネイティブのPythonコードに簡単に置き換えることができます。
echo $PATH
使用して実行しようとしましたcall(["echo", "$PATH"])
が$PATH
、置換を行う代わりにリテラル文字列をエコーしました。PATH環境変数を取得できることはわかっていますが、コマンドをbashで実行したかのように正確に動作させる簡単な方法があるかどうか疑問に思っています。