2009-11-06 12 views
33

मुझे subprocess.call का उपयोग करके एक पायथन प्रक्रिया से उत्पन्न बाहरी कमांड लाइन ऐप्स द्वारा उठाए गए समय और सीपीयू को सीमित करने की आवश्यकता है, मुख्य रूप से क्योंकि कभी-कभी स्पॉन्डेड प्रक्रिया अटक जाती है और 99% पर सीपीयू पिन करती है।पायथन: subimocess.call/subprocess.Popen के लिए ulimit और अच्छा?

अच्छा और उलिमिट ऐसा करने के उचित तरीकों की तरह प्रतीत होता है, लेकिन मुझे यकीन नहीं है कि वे सबप्रोसेस के साथ कैसे बातचीत करेंगे। अगर यह

  • सीमा यह सीपीयू
  • के 20% तक अधिक से अधिक 60 सेकंड ले रहा है
    • प्रक्रिया को मारने मैं सीमित संसाधन लागू करना चाहते हैं:

      • सीमा कुछ इस प्रकार दिखाई subprocess के लिए, उपद्रव पैदा करने वाली अजगर प्रक्रिया के लिए नहीं।

      क्या subprocess.call spawned प्रक्रिया के लिए अच्छा और ulimit लागू करने का कोई तरीका है? क्या बेहतर पायथन-मूल विकल्प हैं?

      यह एक लिनक्स (उबंटू) प्रणाली पर है।

  • +1

    आप मेरे उत्तर के बजाय उच्चतम वोट वाले उत्तर को स्वीकार करना चाहेंगे। यह मेरी तुलना में काफी बेहतर है। –

    उत्तर

    10

    आप इस तरह ulimit और nice खोल आदेशों के साथ subprocesses के लिए सीमा निर्धारित कर सकते हैं:

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

    यह CPU समय के 60 सेकंड की सीमा और 15 नोट की एक संतोषप्रदता समायोजन है कि वहाँ के साथ cpuhog चलाता है इस प्रकार 20% सीपीयू थ्रॉटल सेट करने का कोई आसान तरीका नहीं है। प्रक्रिया 100% सीपीयू का उपयोग करेगी जब तक कि एक और (कम अच्छी) प्रक्रिया को सीपीयू की भी आवश्यकता न हो।

    +0

    धन्यवाद विले, आपके द्वारा वर्णित सीपीयू थ्रॉटलिंग महान काम करता है। क्या आपको पता है कि एक स्ट्रिंग के बजाए ब्रैकेट सिंटैक्स के साथ कमांड निर्दिष्ट करने के लिए एक ही चीज़ करना संभव है? – Parand

    +0

    जहां तक ​​मैं कह सकता हूं, आपको काम करने के लिए कुछ स्ट्रिंग में पूरे शेल कमांड को एक स्ट्रिंग में पास करना होगा। –

    +1

    यह वास्तव में समाधान नहीं है जिसे स्वीकार्य उत्तर के रूप में चिह्नित किया जाना चाहिए। उपयोगकर्ता द्वारा प्रदत्त पैरामीटर के संयोजन में, यह आसानी से सुरक्षा छेद खोलने को समाप्त कर सकता है। –

    86

    subprocess.Popen, और संसाधन मॉड्यूल में preexec_fn पैरामीटर का उपयोग करें। उदाहरण:

    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 उपयोग करने के लिए कोशिश कर रहा से एक बेहतर समाधान कई मामलों में है यह हमेशा एक अच्छा विचार खोल के माध्यम से उपप्रक्रिया अंडे देने के लिए नहीं है के बाद से, खासकर जब से यह अक्सर बदसूरत पैरामीटर का कारण बनता है परेशानी का हवाला देते हुए।

    +0

    धन्यवाद एरिक। ऐसा लगता है कि यह बाहरी प्रक्रिया पर नहीं, पाइथन प्रक्रिया पर सीमा निर्धारित करता है? – Parand

    +0

    पायथन प्रक्रिया और उसके सभी बच्चे। (यानी, जिस तरह से यह माना जाता है।))) आदमी पृष्ठ से: वर्तमान प्रक्रिया द्वारा सिस्टम संसाधनों की खपत पर सीमाएं और प्रत्येक प्रक्रिया जो इसे बनाता है, गेट्रलिमिट() कॉल के साथ प्राप्त की जा सकती है, और सेट्रलिमिट के साथ सेट की जा सकती है() कॉल करें। –

    +2

    हां, संसाधन पैकेज पायथन प्रक्रिया (सेटरलिमिट के माध्यम से) पर सीमा निर्धारित करता है - लेकिन मेरे उदाहरण में, यह बच्चे को चलाने के लिए exec() को कॉल करने से पहले subproces.Popen द्वारा बनाई गई उपप्रोसेसर पर सीमा निर्धारित करता है। तो, उदाहरण में, कॉलिंग प्रक्रिया 'सीमाएं प्रभावित नहीं होती हैं, केवल बच्चे की सीमाएं। –

    6

    एरिक यह मेरे लिए आसान हो गया है, लेकिन वह 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 को जो मैं किसी भी तरह से एलर्जी हूँ: यहाँ सवाल पर मेरी ले है। शायद मैं यहाँ बस बूढ़ा और अजीब हूँ, लेकिन मैं इससे बचने की कोशिश करता हूँ!

    +3

    जब आपको पाइथन के बिल्टिन 'ओएस' में पहले से ही 'अच्छा' है तो आपको 'psutil' क्यों चाहिए? – WGH

    +0

    शायद क्योंकि आप 'os.nice' पर पीआईडी ​​पास नहीं कर सकते हैं, लेकिन आप 'psutil' कर सकते हैं। –

    संबंधित मुद्दे