我需要限制我使用subprocess.call从python进程生成的外部命令行应用程序所花费的时间和cpu,主要是因为有时生成的进程被卡住并将cpu的引脚设置为99%。
很好,ulimit似乎是合理的方法,但我不确定他们如何与子进程交互。
有没有办法将nice和ulimit应用于subprocess.call生成的进程?是否有更好的python-native替代品?
这是在linux(ubuntu)系统上。
答案 0 :(得分:99)
将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(),然后执行 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更好,因为通过shell生成子进程并不总是一个好主意,特别是因为它经常导致丑陋的参数引用问题。
答案 1 :(得分:11)
您可以使用ulimit
和nice
shell命令为子进程设置限制,如下所示:
import subprocess
subprocess.Popen('ulimit -t 60; nice -n 15 cpuhog', shell=True)
运行cpuhog
,CPU时间限制为60秒,调整好15次。请注意,没有简单的方法可以设置20%的CPU限制。该过程将使用100%的CPU,除非另一个(不太好)的过程也需要CPU。
答案 2 :(得分:7)
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
我过敏的地方。也许我只是在这里老了,脾气暴躁,但我尽量避免它!