2010-01-18 7 views
94

में मैं एक लंबे चल विरासत गहरे लाल रंग का कार्यक्रम पारित किया गया था, जो इसे भरकैप्चर Ctrl-सी माणिक

begin 
    #dosomething 
rescue Exception => e 
    #halt the exception's progress 
end 

के कई घटनाओं है।

हर एक संभावित अपवाद के इन प्रत्येक (कम से कम तुरंत नहीं) से निपटने के किया जा सकता है पर नज़र रखने के बिना, मैं अभी भी Ctrlसी साथ समय पर इसे बंद करने में सक्षम होना चाहते हैं।

और मैं एक तरह से जो केवल कोड में जोड़ता है (इसलिए मैं मौजूदा व्यवहार को प्रभावित नहीं है, या एक रन के बीच में एक अन्यथा पकड़ा अपवाद याद आती है।)

में ऐसा करना चाहते हैं [Ctrlसी सिगिनट, या सिस्टमएक्सिट है, जो रूबी के अपवाद हैंडलिंग सिस्टम में SignalException.new("INT") के बराबर प्रतीत होता है। class SignalException < Exception, जिसके कारण इस समस्या आ जाती है]

कोड रहा होगा लिखा है करना चाहते हैं:।

begin 
    #dosomething 
rescue SignalException => e 
    raise e 
rescue Exception => e 
    #halt the exception's progress 
end 

संपादित करें: इस कोड काम करता है, जब तक कि आप अपवाद के वर्ग मिल आप सही जाल करना चाहते हैं। यह या तो SystemExit, इंटरप्ट, या आईआरबी :: नीचे के रूप में निरस्त है।

उत्तर

113

समस्या यह है कि जब रूबी प्रोग्राम समाप्त होता है, तो यह SystemExit उठाकर ऐसा करता है। जब एक नियंत्रण-सी आता है, तो यह को बाधित करता है। चूंकि SystemExit और इंटरप्टअपवाद से प्राप्त होता है, तो आपका अपवाद हैंडलिंग बाहर निकलने से रोकता है या अपने ट्रैक में बाधा डालता है। यहाँ ठीक है:

rescue Exception => e 
    # ... 
    raise 
end 
:

आप जहां कहीं भी, बदल सकते हैं

rescue Exception => e 
    # ... 
end 

को

rescue StandardError => e 
    # ... 
end 
उन आप StandardError को नहीं बदल सकते हैं के लिए

, अपवाद फिर से बढ़ा

या, कम से कम, सिस्टमएक्सिट को फिर से बढ़ाएं और

rescue SystemExit, Interrupt 
    raise 
rescue Exception => e 
    #... 
end 

आप StandardErrorसे निकाले जाते हैं चाहिए बना दिया है किसी भी कस्टम अपवाद नहीं अपवाद

+0

वेन, क्या आप अपनी सूची में आईआरबी :: निरस्त उदाहरण जोड़ने के लिए बहुत दयालु होंगे? –

+1

@ टिम, irb.rb (मेरे सिस्टम पर, यह /usr/lib/ruby/1.8/irb.rb में है) ढूंढें और मुख्य पाश ढूंढें (@ context.evaluate के लिए खोजें)। बचाव खंडों को देखें और मुझे लगता है कि आप समझेंगे कि आईआरबी इस तरह से व्यवहार क्यों कर रहा है। –

+0

धन्यवाद। Irb.rb में #signal_handle की परिभाषा को देखते हुए मेरी समझ में भी मदद मिली। उनके मुख्य लूप के अपवाद परिवर्तनीय बाध्यकारी के भीतर भी एक साफ चाल है। (बचाव खंडों का उपयोग एक विशिष्ट अपवाद को चुनने के तरीके के रूप में करते हुए, फिर बचाव निकायों के बाहर उस अपवाद का उपयोग करना।) –

63

आप अपने पूरे कार्यक्रम लपेट कर सकते हैं आप निम्नलिखित की तरह कुछ कर सकते हैं:

trap("SIGINT") { throw :ctrl_c } 

catch :ctrl_c do 
begin 
    sleep(10) 
rescue Exception 
    puts "Not printed" 
end 
end 

यह मूलतः है Ctrlसी उपयोग पकड़/अपवाद संचालन के बजाय फेंक, इसलिए जब तक पहले से ही विद्यमान कोड इसमें एक पकड़ है: ctrl_c इसमें, यह ठीक होना चाहिए।

वैकल्पिक रूप से आप trap("SIGINT") { exit! } कर सकते हैं। exit! तुरंत निकलता है, यह अपवाद नहीं बढ़ाता है इसलिए कोड गलती से इसे पकड़ नहीं सकता है।

+2

ध्यान दें कि आईआरबी में Ctrl-C आईआरबी भेजता है :: Abort, SIGINT नहीं। अन्यथा @ लोगान का जवाब एक समाधान है। –

+1

@ टिमसोन्हाइट रूबी दुभाषिया 'सिगिनट' के लिए मेरे लिए ठीक काम करता है। – defhlt

+1

फेंक और पकड़ एक ही थ्रेड पर होना चाहिए, इसलिए यदि आप किसी अन्य थ्रेड पर इंटरप्ट अपवाद को पकड़ना चाहते हैं तो यह काम नहीं करेगा। –

25

आप एक begin ... rescue ब्लॉक (जैसे, थोर) में अपने पूरे आवेदन लपेट नहीं कर सकते तो आप सिर्फ जाल SIGINT कर सकते हैं:

trap "SIGINT" do 
    puts "Exiting" 
    exit 130 
end 

130 एक मानक से बाहर निकलें कोड है।

+0

एफवाईआई, 130 Ctrl-C बाधित स्क्रिप्ट के लिए सही निकास कोड है: https://www.google.com/search?q=130+exit+code&en= ('130 | कंट्रोल-सी | सीटीएल-सी द्वारा समाप्त स्क्रिप्ट | नियंत्रण-सी घातक त्रुटि संकेत 2 है, (130 = 128 + 2, ऊपर देखें) ') – Dorian

3

मैं ensure का उपयोग बहुत प्रभाव से कर रहा हूं! यह उन चीज़ों के लिए है जब आप अपनी चीजें समाप्त करते हैं, इससे कोई फर्क नहीं पड़ता कि यह क्यों समाप्त होता है।