سؤال

أحتاج إلى تحديد مقدار الوقت ووحدة المعالجة المركزية التي تستغرقها تطبيقات سطر الأوامر الخارجية التي أنشئها من عملية بايثون باستخدام subprocess.call، وذلك لأنه في بعض الأحيان تتعطل العملية التي تم إنشاؤها وتثبت وحدة المعالجة المركزية بنسبة 99٪.

يبدو أن Nice وUlimit هما طريقتان معقولتان للقيام بذلك، لكنني لست متأكدًا من كيفية تفاعلهما مع العملية الفرعية.

  • تبدو الحدود كما يلي:
    • قم بإنهاء العملية إذا كانت تستغرق أكثر من 60 ثانية
    • حدده بـ 20٪ من وحدة المعالجة المركزية
  • أريد تطبيق تحديد الموارد على العملية الفرعية، وليس على عملية بايثون التي تنتج العمليات الفرعية.

هل هناك طريقة لتطبيق لطيف وUlimit على عملية subprocess.call الناتجة؟هل هناك بدائل أفضل لبيثون؟

وهذا على نظام لينكس (أوبونتو).

هل كانت مفيدة؟

المحلول

يمكنك تعيين حدود للعمليات الفرعية باستخدام الملف ulimit و nice أوامر shell مثل هذا:

import subprocess
subprocess.Popen('ulimit -t 60; nice -n 15 cpuhog', shell=True)

هذا يعمل cpuhog بحد أقصى 60 ثانية من وقت وحدة المعالجة المركزية وتعديل لطيف يبلغ 15 ثانية.لاحظ أنه لا توجد طريقة بسيطة لضبط سرعة وحدة المعالجة المركزية بنسبة 20% على هذا النحو.ستستخدم العملية وحدة المعالجة المركزية بنسبة 100% ما لم تحتاج عملية أخرى (أقل روعة) إلى وحدة المعالجة المركزية أيضًا.

نصائح أخرى

استخدم المعلمة 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، نظرًا لأنه ليس من الجيد دائمًا إنتاج عملية فرعية عبر Shell، خاصة أنه غالبًا ما يتسبب في حدوث مشكلة في اقتباس المعلمات القبيحة.

إريك سهلت الأمر علي، لكنه نسي 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 الذي لدي حساسية منه إلى حد ما.ربما أنا فقط عجوز وغاضب هنا، لكني أحاول تجنب ذلك!

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top