Python : Ulimit과 Subprocess.call / subprocess.popen에 좋은?
문제
하위 프로세스를 사용하여 Python 프로세스에서 스폰 된 외부 명령 줄 앱에서 취한 시간과 CPU를 제한해야합니다.
Nice and Ulimit 은이 작업을 수행하는 합리적인 방법처럼 보이지만, 그들이 어떻게 하위 프로세스와 상호 작용하는지 잘 모르겠습니다.
- 한계는 다음과 같습니다.
- 60 초 이상 걸리면 프로세스를 죽여
- CPU의 20%로 제한하십시오
- 하위 프로세스를 산란하는 파이썬 프로세스가 아니라 하위 프로세스에 리소스 제한을 적용하고 싶습니다.
Subprocess.call Spawned 프로세스에 Nice and Ulimit을 적용하는 방법이 있습니까? 더 나은 파이썬 네이티브 대안이 있습니까?
이것은 Linux (Ubuntu) 시스템에 있습니다.
해결책
서브 프로세서에 대한 제한을 설정할 수 있습니다 ulimit
그리고 nice
다음과 같은 쉘 명령 :
import subprocess
subprocess.Popen('ulimit -t 60; nice -n 15 cpuhog', shell=True)
이것은 실행됩니다 cpuhog
60 초의 CPU 시간과 15의 냉장 조정으로 20% CPU 스로틀을 설정하는 간단한 방법은 없습니다. 프로세스는 다른 (덜 NIC) 프로세스에도 CPU가 필요하지 않으면 100% CPU를 사용합니다.
다른 팁
preexec_fn 매개 변수를 사용하여 하위 프로세스 .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을 사용하는 것보다 더 나은 솔루션입니다. 특히 쉘을 통해 하위 프로세스를 스폰하는 것이 항상 좋은 아이디어는 아니기 때문입니다. 특히 추악한 매개 변수 인용 문제가 발생하기 때문입니다.
에릭 나를 쉽게 만들었지 만 그는 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()
빌 사용 shell=True
나는 어떻게 든 알레르기가 있습니다. 아마도 나는 여기서 나이가 많고 심술 궂지 만 피하려고 노력합니다!