pythonプロセスをsubprocess.callを使用して作成した外部コマンドラインアプリが使用する時間とCPUの量を制限する必要があります。主に、作成されたプロセスがスタックし、CPUを99にピン留めするためです。 %。
Niceとulimitはこれを行うための合理的な方法のように見えますが、サブプロセスとどのように相互作用するかはわかりません。
Niceとulimitをsubprocess.call生成されたプロセスに適用する方法はありますか? Pythonネイティブの代替案はありますか?
これはLinux(ubuntu)システム上にあります。
次のようなulimit
およびNice
シェルコマンドを使用して、サブプロセスの制限を設定できます。
import subprocess
subprocess.Popen('ulimit -t 60; Nice -n 15 cpuhog', Shell=True)
これはcpuhog
を実行し、制限は60秒のCPU時間と15のナイスネス調整です。20%のCPUスロットルをそのように設定する簡単な方法はないことに注意してください。別の(Niceが少ない)プロセスもCPUを必要としない限り、プロセスは100%CPUを使用します。
Preexec_fnパラメータをsubprocess.Popenとリソースモジュールに使用します。例:
parent.py:
#!/usr/bin/env python
import os
import sys
import resource
import subprocess
def setlimits():
# Set maximum CPU time to 1 second in child process, after fork() but before exec()
print "Setting resource limit in child (pid %d)" % os.getpid()
resource.setrlimit(resource.RLIMIT_CPU, (1, 1))
print "CPU limit of parent (pid %d)" % os.getpid(), resource.getrlimit(resource.RLIMIT_CPU)
p = subprocess.Popen(["./child.py"], preexec_fn=setlimits)
print "CPU limit of parent (pid %d) after startup of child" % os.getpid(), resource.getrlimit(resource.RLIMIT_CPU)
p.wait()
print "CPU limit of parent (pid %d) after child finished executing" % os.getpid(), resource.getrlimit(resource.RLIMIT_CPU)
child.py:
#!/usr/bin/env python
import os
import sys
import resource
print "CPU limit of child (pid %d)" % os.getpid(), resource.getrlimit(resource.RLIMIT_CPU)
parent.pyは新しいプロセスに分岐します。新しいプロセスでは、setlimits()を呼び出してから、exec child.pyを実行します。つまり、リソースは子プロセスでは制限されますが、親プロセスでは制限されません。
プログラム実行時の出力:
./parent.py
CPU limit of parent (pid 17404) (-1, -1)
Setting resource limit in child (pid 17405)
CPU limit of parent (pid 17404) after startup of child (-1, -1)
CPU limit of child (pid 17405) (1, 1)
CPU limit of parent (pid 17404) after child finished executing (-1, -1)
これは多くの場合、ulimitを使用するよりも優れたソリューションです。シェルを介してサブプロセスを生成することは常に良い考えとは限らないためです。
Erikを使用すると簡単になりましたが、Richが指摘したNice
の部分を忘れていました。私はpsutil
パッケージを見つけました。これは私の質問に対する私の見解です:
import os
import psutil
import resource
import subprocess
def preexec_fn():
pid = os.getpid()
ps = psutil.Process(pid)
ps.set_Nice(10)
resource.setrlimit(resource.RLIMIT_CPU, (1, 1))
print "mother pid", os.getpid()
p = subprocess.Popen(["./cpuhog.sh"], preexec_fn=preexec_fn)
p.wait()
print "mother still alive with pid", os.getpid()
VilleはShell=True
なんとなくアレルギーです。たぶん私はここで年老いて不機嫌ですが、それを避けようとしています!