2015-01-06 8 views
32

मैं निम्नलिखित कोड है बंद करने से पहले खत्म करने के लिए:जब asyncio का उपयोग कर, आप कैसे अनुमति नहीं सभी में चल रहे कार्यों घटना पाश

@asyncio.coroutine 
def do_something_periodically(): 
    while True: 
     asyncio.async(my_expensive_operation()) 
     yield from asyncio.sleep(my_interval) 
     if shutdown_flag_is_set: 
      print("Shutting down") 
      break 

मैं पूरा जब तक इस समारोह चलाते हैं। समस्या तब होती है जब शट डाउन सेट होता है - फ़ंक्शन पूरा हो जाता है और कोई लंबित कार्य कभी नहीं चलाया जाता है। (आप इसे एक त्रुटि के रूप में देखते हैं

task: <Task pending coro=<report() running at script.py:33> wait_for=<Future pending cb=[Task._wakeup()]>> 

)। मैं शट डाउन को सही तरीके से कैसे शेड्यूल करूं?

कुछ संदर्भ देने के लिए, मैं एक सिस्टम मॉनिटर लिख रहा हूं जो हर 5 सेकंड में/proc/stat से पढ़ता है, उस अवधि में सीपीयू उपयोग की गणना करता है, और फिर परिणाम को सर्वर पर भेजता है। मैं इन निगरानी नौकरियों को शेड्यूल करना चाहता हूं जब तक कि मैं सिगरेट प्राप्त नहीं करता, जब मैं शेड्यूलिंग रोकता हूं, सभी मौजूदा नौकरियों को समाप्त करने की प्रतीक्षा करता हूं, और शानदार तरीके से बाहर निकलता हूं।

+0

कुछ संदर्भ देने के लिए, मैं एक प्रणाली की निगरानी से दूर/proc/stat हर 5 सेकंड पढ़ता लिख ​​रहा हूँ: इस मामले में, के बाद से सभी कार्य एक ही coroutine में बनाए जाते हैं, आप पहले से ही कार्य के लिए उपयोग किया , उस अवधि में सीपीयू उपयोग की गणना करता है, और फिर परिणाम को एक से भेजता है rver। मैं इन निगरानी नौकरियों को शेड्यूल करना चाहता हूं जब तक कि मैं सिगरेट प्राप्त नहीं करता, जब मैं शेड्यूलिंग रोकता हूं, सभी मौजूदा नौकरियों को समाप्त करने की प्रतीक्षा करता हूं, और शानदार तरीके से बाहर निकलता हूं। – derekdreery

+0

क्या आपने my_expensive_operation() \ n से उपज की कोशिश की है asyncio.sleep (my_interval - timer()% my_interval) 'इसके बजाय? – jfs

+0

मैं बस इतनी देर तक सो सकता था कि मुझे पता है कि सब कुछ खत्म हो गया है, लेकिन यह बहुत साफ नहीं लगता है। मैं सोच रहा था कि कार्यों को शेड्यूल करने का कोई तरीका था या फिर लूप चलाएं जब तक सभी निर्धारित कार्य पूर्ण नहीं हो जाते। जावास्क्रिप्ट (node.js) में, यदि मुख्य प्रोग्राम अंत तक पहुंचता है लेकिन कॉलबैक सेट होते हैं, तो प्रक्रिया तब तक चलती है जब तक सभी कॉलबैक हटा दिए जाते हैं। – derekdreery

उत्तर

33

आप अधूरे कार्यों को पुनर्प्राप्त कर सकते हैं और लूप को फिर से समाप्त कर सकते हैं, फिर लूप बंद करें या अपने प्रोग्राम से बाहर निकलें।

pending = asyncio.Task.all_tasks() 
loop.run_until_complete(asyncio.gather(*pending)) 
  • लंबित लंबित कार्यों की एक सूची है।
  • asyncio.gather() एक साथ कई कार्यों पर इंतजार करने की अनुमति देता है। में

    @asyncio.coroutine 
    def do_something_periodically(): 
        while True: 
         asyncio.async(my_expensive_operation()) 
         yield from asyncio.sleep(my_interval) 
         if shutdown_flag_is_set: 
          print("Shutting down") 
          break 
    
        yield from asyncio.gather(*asyncio.Task.all_tasks()) 
    

    इसके अलावा,:

आप सभी कार्य सुनिश्चित करना चाहते हैं एक coroutine (हो सकता है आप एक "मुख्य" coroutine हैं) तो आप इसे इस तरह, कर सकते हैं, उदाहरण के लिए अंदर पूरा कर रहे हैं

@asyncio.coroutine 
def do_something_periodically(): 
    tasks = [] 
    while True: 
     tasks.append(asyncio.async(my_expensive_operation())) 
     yield from asyncio.sleep(my_interval) 
     if shutdown_flag_is_set: 
      print("Shutting down") 
      break 

    yield from asyncio.gather(*tasks) 
+1

बहुत उपयोगी! दूसरी विधि के बारे में सिर्फ एक नोट: मैं * सोचता हूं कि सूची में शामिल प्रत्येक कार्य एक खुली फ़ाइल डिस्क्रिप्टर का प्रतिनिधित्व करता है - इसका मतलब है कि लिनक्स पर, आप अपनी खुली फ़ाइल सीमा ('ulimit -n') पहले हिट कर सकते हैं coroutine खत्म हो गया है। – detly

+0

हाय, "प्रतिनिधित्व" से आपका क्या मतलब है? AFAIK, कार्य फ़ाइल ऑब्जेक्ट्स नहीं खोलते हैं। –

+0

मैंने दूसरी विधि का उपयोग करके पाया है, कि मुझे बहुत से खुले फ़ाइल डिस्क्रिप्टर होने के बारे में त्रुटि संदेश मिलते हैं। मैं * सोचता हूं कि प्रत्येक कार्य को काम करने के लिए फ़ाइल डिस्क्रिप्टर की आवश्यकता होती है। ध्यान दें कि एक "फ़ाइल डिस्क्रिप्टर" एक खुली फ़ाइल के समान नहीं है, इसलिए वे ['select()'] (http://www.gnu.org/software/libc/manual/) द्वारा उपयोग किए जा सकते हैं html_node/प्रतीक्षा कर रहा है-I_002fO के लिए।एचटीएमएल # इंडेक्स-फाइल-डिस्क्रिप्टर-सेट_002 सी-फॉर-सिलेक्ट) कॉल (जो मुझे लगता है कि 'asyncio' लाइब्रेरी का उपयोग करता है)। इसलिए यदि आपके पास कुछ हज़ार खुली फ़ाइल डिस्क्रिप्टर की उपयोगकर्ता सीमा है, और उससे अधिक कार्य हैं, तो आपको समस्याएं आ सकती हैं। – detly

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