2015-03-20 6 views
20

मैं कुछ सरल मल्टीथ्रेड किए गए I/O करने के लिए नए concurrent.futures मॉड्यूल (जिसमें पाइथन 2 बैकपोर्ट भी है) का उपयोग कर रहा हूं। मुझे इस मॉड्यूल का उपयोग शुरू करने वाले कार्यों को साफ तरीके से मारने के तरीके को समझने में समस्या हो रही है।एक बार शुरू होने के बाद आप वायदा को कैसे मार सकते हैं?

चेक बाहर निम्नलिखित पायथन 2/3 स्क्रिप्ट है, जो व्यवहार मैं दिखाई दे रही है reproduces:

#!/usr/bin/env python 
from __future__ import print_function 

import concurrent.futures 
import time 


def control_c_this(): 
    with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: 
     future1 = executor.submit(wait_a_bit, name="Jack") 
     future2 = executor.submit(wait_a_bit, name="Jill") 

     for future in concurrent.futures.as_completed([future1, future2]): 
      future.result() 

     print("All done!") 


def wait_a_bit(name): 
    print("{n} is waiting...".format(n=name)) 
    time.sleep(100) 


if __name__ == "__main__": 
    control_c_this() 

इस स्क्रिप्ट यह सफाई से नियमित रूप से नियंत्रण सी कुंजीपटल बाधा का उपयोग कर मारने के लिए असंभव प्रतीत होता है चल रहा हो। मैं ओएस एक्स

  • पर चल रहा अजगर 2.7 पर मैं कमांड लाइन से kill का सहारा लेना स्क्रिप्ट को मारने के लिए की है। नियंत्रण-सी सिर्फ अनदेखा किया जाता है।
  • पायथन 3.4 पर, नियंत्रण-सी काम करता है यदि आप इसे दो बार दबाते हैं, लेकिन फिर बहुत सारे अजीब स्टैक निशान डंप किए जाते हैं।

अधिकांश प्रलेखन मैं कैसे सफाई से वर्ष threading मॉड्यूल के साथ धागे को मारने के लिए के बारे में ऑनलाइन वार्ता पाया है। ऐसा कोई भी यहां लागू नहीं होता है।

और यह सब concurrent.futures मॉड्यूल के भीतर प्रदान की गई विधियों सामान को रोकने के लिए (जैसे Executor.shutdown() और Future.cancel()) ही काम करते हैं जब वायदा अभी तक शुरू नहीं किया है या पूरा, जो इस मामले में व्यर्थ है कर रहे हैं। मैं तुरंत भविष्य में बाधा डालना चाहता हूं।

मेरा उपयोग मामला सरल है: जब उपयोगकर्ता नियंत्रण-सी को हिट करता है, तो स्क्रिप्ट को किसी भी अच्छी तरह से व्यवहार की गई स्क्रिप्ट की तरह तुरंत बाहर निकलना चाहिए। मुझे यही सब चाहिए था।

तो concurrent.futures का उपयोग करते समय इस व्यवहार को पाने का सही तरीका क्या है?

+0

एक [जावा के बारे में संबंधित प्रश्न] (http://stackoverflow.com/q/671049/877069) पढ़ना, मुझे लगता है कि एक धागा की हत्या कुछ है क्योंकि यह आपके प्रोग्राम स्थिति असंगत बना सकते हैं आप आमतौर पर करते नहीं है । मेरे मामले में मैं नहीं सोचता * यह एक चिंता है क्योंकि मैं सिर्फ पूरा कार्यक्रम बाहर निकलना चाहता हूं। [कुछ साझा चर सेटिंग] का भी उल्लेख किया गया था (http://stackoverflow.com/a/11387729/877069) कि धागे स्वयं को समाप्त करने के बारे में जानने के लिए पढ़ सकते हैं। सुनिश्चित नहीं है कि वह दृष्टिकोण पाइथन पर चलता है। –

+0

बस एक सिर ऊपर, Ctrl + Break काम करेगा, भले ही Ctrl + C नहीं है। – jedwards

+0

@jedwards - पायथन 2 के साथ मैं कमांड + कोशिश कर रहा हूं। (जो ओएस एक्स पर नियंत्रण + ब्रेक है) और यह काम नहीं कर रहा है। वास्तव में नियंत्रण + सी के बराबर लगता है। –

उत्तर

12

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

यहां बताया गया है कि quote क्यों है। संक्षेप में, यदि दुभाषिया करता है तो धागे निकलते हैं, बुरी चीजें हो सकती हैं।

यहां एक कामकाजी उदाहरण है। ध्यान दें कि सी-सी को प्रसारित करने के लिए अधिकतम 1 सेकंड लगते हैं क्योंकि बच्चे के धागे की नींद की अवधि।

#!/usr/bin/env python 
from __future__ import print_function 

import concurrent.futures 
import time 
import sys 

quit = False 
def wait_a_bit(name): 
    while not quit: 
     print("{n} is doing work...".format(n=name)) 
     time.sleep(1) 

def setup(): 
    executor = concurrent.futures.ThreadPoolExecutor(max_workers=5) 
    future1 = executor.submit(wait_a_bit, "Jack") 
    future2 = executor.submit(wait_a_bit, "Jill") 

    # main thread must be doing "work" to be able to catch a Ctrl+C 
    # http://www.luke.maurits.id.au/blog/post/threads-and-signals-in-python.html 
    while (not (future1.done() and future2.done())): 
     time.sleep(1) 

if __name__ == "__main__": 
    try: 
     setup() 
    except KeyboardInterrupt: 
     quit = True 
+0

अब मैं ले जाऊंगा कि यह सबसे अच्छा समाधान है। यह बेकार है कि आपको अपने धागे को नींद पाश के साथ CPU समय जला देना है। और भी, जितना अधिक उत्तरदायी आप मारना चाहते हैं, उतना ही कम नींद लूप होना चाहिए और इस प्रकार, अधिक CPU समय जला दिया जाता है। –

+1

आपको सोने की ज़रूरत नहीं है। आपको बस उन्हें जांचने की आवश्यकता है कि उन्हें बाहर निकलना चाहिए या नहीं। – cdosborn

+1

'ट्रिपपूलएक्ससेलर' का उपयोग करते समय यह चाल मेरे लिए काम करती है लेकिन 'ProcessPoolExecutor' के साथ नहीं। प्रक्रियाओं में वैश्विक चर साझा करने का प्रयास करते समय क्या कुछ गोचा गया है? क्या मुझे डिस्क या कुछ पर 'छोड़ने' ध्वज को स्टोर करना होगा? –

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

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