Python: ulimit and nice for subprocess.call / subprocess.Popen?

2024/11/19 15:22:33

I need to limit the amount of time and cpu taken by external command line apps I spawn from a python process using subprocess.call , mainly because sometimes the spawned process gets stuck and pins the cpu at 99%.

nice and ulimit seem like reasonable ways to do this, but I'm not sure how they'd interact with subprocess.

  • The limits look something like:
    • Kill the process if it's taking more than 60 seconds
    • Limit it to 20% of cpu
  • I want to apply the resource limiting to the subprocess, not to the python process that's spawning the subprocesses.

Is there a way to apply nice and ulimit to the subprocess.call spawned process? Are there better python-native alternatives?

This is on a linux (ubuntu) system.

Answer

Use the preexec_fn parameter to subprocess.Popen, and the resource module. Example:

parent.py:

#!/usr/bin/env pythonimport os
import sys
import resource
import subprocessdef 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 pythonimport os
import sys
import resourceprint "CPU limit of child (pid %d)" % os.getpid(), resource.getrlimit(resource.RLIMIT_CPU)

parent.py will fork into a new process. In the new process, it will call setlimits(), then exec child.py. This means the resource will be limited in the child process, but not in the parent.

Output when running program:

./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)

This is in many cases a better solution than trying to use ulimit, since it's not always a good idea to spawn subprocess via shell, especially since it often causes ugly parameter quoting trouble.

https://en.xdnf.cn/q/26424.html

Related Q&A

array.shape() giving error tuple not callable

I have a 2D numpy array called results, which contains its own array of data, and I want to go into it and use each list: for r in results:print "r:"print ry_pred = np.array(r)print y_pred.sh…

Python unittest - Ran 0 tests in 0.000s

So I want to do this code Kata for practice. I want to implement the kata with tdd in separate files:The algorithm:# stringcalculator.py def Add(string):return 1and the tests:# stringcalculator.spec.…

How and where does py.test find fixtures

Where and how does py.test look for fixtures? I have the same code in 2 files in the same folder. When I delete conftest.py, cmdopt cannot be found running test_conf.py (also in same fo…

Python match a string with regex [duplicate]

This question already has answers here:What exactly do "u" and "r" string prefixes do, and what are raw string literals?(7 answers)What exactly is a "raw string regex" an…

What are the consequences of disabling gossip, mingle and heartbeat for celery workers?

What are the implications of disabling gossip, mingle, and heartbeat on my celery workers?In order to reduce the number of messages sent to CloudAMQP to stay within the free plan, I decided to follow …

How to determine if an exception was raised once youre in the finally block?

Is it possible to tell if there was an exception once youre in the finally clause? Something like:try:funky code finally:if ???:print(the funky code raised)Im looking to make something like this m…

How to use re match objects in a list comprehension

I have a function to pick out lumps from a list of strings and return them as another list:def filterPick(lines,regex):result = []for l in lines:match = re.search(regex,l)if match:result += [match.grou…

How do I run pip on python for windows? [duplicate]

This question already has answers here:Why does "pip install" inside Python raise a SyntaxError?(6 answers)Closed 8 years ago.Ive just installed python 3.5, ran Python 3.5 (32-bit) and typed…

Select certain rows by index of another DataFrame

I have a DataFrame and I would select only rows that contain index value into df1.index. for Example: In [96]: df Out[96]:A B C D 1 1 4 9 1 2 4 5 0 2 3 5 5 1 0 22 1 3 9 6and these ind…

Execute .sql schema in psycopg2 in Python

I have a PostgreSQL schema stored in .sql file. It looks something like:CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY,facebook_id TEXT NOT NULL,name TEXT NOT NULL,access_token TEXT,created I…