シェルスクリプトをもっと読みやすいPythonバージョンに移植しようとしています。元のシェルスクリプトは、バックグラウンドで「&」を使用していくつかのプロセス(ユーティリティ、モニターなど)を開始します。Pythonで同じ効果を達成するにはどうすればよいですか?Pythonスクリプトが完了したときにこれらのプロセスが停止しないようにしたいと思います。どういうわけかデーモンの概念に関係していると思いますが、簡単にこれを行う方法を見つけることができませんでした。
9 に答える
jkpのソリューションは機能しますが、物事を行う新しい方法 (およびドキュメントが推奨する方法) は、subprocess
モジュールを使用することです。単純なコマンドの場合は同等ですが、複雑なことをしたい場合は、より多くのオプションが提供されます。
あなたのケースの例:
import subprocess
subprocess.Popen(["rm","-r","some.file"])
これはrm -r some.file
バックグラウンドで実行されます。.communicate()
から返されたオブジェクトを呼び出すと、Popen
完了するまでブロックされることに注意してください。バックグラウンドで実行したい場合は、そうしないでください。
import subprocess
ls_output=subprocess.Popen(["sleep", "30"])
ls_output.communicate() # Will block for 30 seconds
こちらのドキュメントを参照してください。
また、明確化のポイント: ここで使用する「背景」は、純粋にシェルの概念です。技術的には、完了するのを待つ間、ブロックせずにプロセスを生成したいということです。ただし、ここではシェルの背景のような動作を指すために「背景」を使用しました。
注:この回答は、2009年に投稿されたときよりも最新ではありません。ドキュメントでsubprocess
は、他の回答に示されているモジュールを使用することが推奨されています
( subprocess モジュールは、新しいプロセスを生成し、その結果を取得するためのより強力な機能を提供することに注意してください。これらの関数を使用するよりも、そのモジュールを使用することをお勧めします。)
プロセスをバックグラウンドで開始したい場合はsystem()
、シェルスクリプトと同じ方法でプロセスを使用して呼び出すか、次のようにすることができspawn
ます。
import os
os.spawnl(os.P_DETACH, 'some_long_running_command')
(または、移植性の低いos.P_NOWAIT
フラグを試すこともできます)。
こちらのドキュメントを参照してください。
おそらく、 「Python で外部コマンドを呼び出す方法」への回答が必要です。
最も簡単な方法は、os.system
関数を使用することです。次に例を示します。
import os
os.system("some_command &")
基本的に、関数に渡すものは何でもsystem
、スクリプトでシェルに渡した場合と同じように実行されます。
私はここでこれを見つけました:
Windows(win xp)では、親プロセスは、longtask.py
が作業を終了するまで終了しません。これは、CGIスクリプトで必要なものではありません。問題はPythonに固有のものではなく、PHPコミュニティでも問題は同じです。
DETACHED_PROCESS
解決策は、プロセス作成フラグをwinAPIの基になるCreateProcess
関数に渡すことです。pywin32をインストールした場合は、win32processモジュールからフラグをインポートできます。それ以外の場合は、自分でフラグを定義する必要があります。
DETACHED_PROCESS = 0x00000008
pid = subprocess.Popen([sys.executable, "longtask.py"],
creationflags=DETACHED_PROCESS).pid
subprocess.Popen()
このパラメーターを使用するとclose_fds=True
、生成されたサブプロセスを Python プロセス自体から切り離し、Python の終了後も実行を継続できます。
https://gist.github.com/yinjimmy/d6ad0742d03d54518e9f
import os, time, sys, subprocess
if len(sys.argv) == 2:
time.sleep(5)
print 'track end'
if sys.platform == 'darwin':
subprocess.Popen(['say', 'hello'])
else:
print 'main begin'
subprocess.Popen(['python', os.path.realpath(__file__), '0'], close_fds=True)
print 'main end'
さまざまなスレッドを fork するための os モジュールの調査を開始することをお勧めします (対話型セッションを開いて help(os) を発行することにより)。関連する機能は fork と exec のいずれかです。開始方法についてのアイデアを得るために、フォークを実行する関数に次のようなものを入れます (関数は、プログラムの名前とそのパラメーターを含む引数として、リストまたはタプル 'args' を取る必要があります。新しいスレッドの stdin、out、および err を定義します):
try:
pid = os.fork()
except OSError, e:
## some debug output
sys.exit(1)
if pid == 0:
## eventually use os.putenv(..) to set environment variables
## os.execv strips of args[0] for the arguments
os.execv(args[0], args)