मुझे राइट-एरर बनाम थ्रो का उपयोग कब करना चाहिए? समाप्ति बनाम गैर-समाप्ति त्रुटियों


145

पॉशकोड, http://poshcode.org/3226 पर एक Get-WebFile स्क्रिप्ट को देखते हुए , मैंने इस अजीब से दिखने वाले गर्भनिरोधक पर ध्यान दिया:

$URL_Format_Error = [string]"..."
Write-Error $URL_Format_Error
return

निम्नलिखित के विपरीत इसका क्या कारण है?

$URL_Format_Error = [string]"..."
Throw $URL_Format_Error

या इससे भी बेहतर:

$URL_Format_Error = New-Object System.FormatException "..."
Throw $URL_Format_Error

जैसा कि मैं समझता हूं, आपको गैर-समाप्ति त्रुटियों के लिए लिखने-त्रुटि का उपयोग करना चाहिए, और त्रुटियों को समाप्त करने के लिए फेंकना चाहिए, इसलिए यह मुझे लगता है कि आपको रिटर्न के बाद लिखने-त्रुटि का उपयोग नहीं करना चाहिए। क्या कोई अंतर है?


4
आपका क्या अर्थ है? अगर Write_error स्क्रिप्ट को जारी रखने की अनुमति देता है, तो राइट-एरर के बाद रिटर्न स्टेटमेंट होना बहुत ही समझ में आता है। त्रुटि बाहर लिखी गई है और आप उस कोड पर वापस लौटते हैं जिसे फ़ंक्शन पहले स्थान पर कहते हैं। चूंकि थ्रो त्रुटियों को समाप्त करने के लिए है, इसलिए यह स्वचालित रूप से समाप्त हो जाएगा ताकि फेंक घोषणा में एक वापसी बयान बेकार हो
गिस्ली

1
@ गिस्ली: यह नोट करना महत्वपूर्ण है कि एक (उन्नत) फ़ंक्शन के ब्लॉक में कॉलर वापस नहींreturn आता है ; इसके बजाय, यह पाइपलाइन में अगले इनपुट ऑब्जेक्ट के लिए आगे बढ़ता है । वास्तव में, यह गैर-समाप्ति त्रुटियों को उत्पन्न करने के लिए विशिष्ट परिदृश्य है: यदि आगे इनपुट वस्तुओं को संसाधित करना अभी भी संभव है। process
mklement0

1
ध्यान दें कि Throwएक स्क्रिप्ट -त्रुटि उत्पन्न करता है , जो कि कथन के अनुसार समान नहीं है-त्रुटि त्रुटियों को ट्रिगर करता है, उदाहरण के लिए, Get-Item -NoSuchParameterया 1 / 0
mklement0

जवाबों:


188

Write-Errorयदि आप किसी गैर-महत्वपूर्ण त्रुटि के उपयोगकर्ता को सूचित करना चाहते हैं, तो इसका उपयोग किया जाना चाहिए। डिफ़ॉल्ट रूप से यह सब कुछ कंसोल पर लाल पाठ में एक त्रुटि संदेश प्रिंट करता है। यह एक पाइपलाइन या लूप को जारी रखने से नहीं रोकता है। Throwदूसरी ओर वह उत्पन्न करता है जिसे समाप्ति त्रुटि कहा जाता है। यदि आप थ्रो का उपयोग करते हैं, तो पाइपलाइन और / या वर्तमान लूप समाप्त हो जाएंगे। वास्तव में जब तक आप समाप्ति त्रुटि को संभालने के लिए संरचना trapया try/catchसंरचना का उपयोग नहीं करते तब तक सभी निष्पादन समाप्त हो जाएंगे ।

नोट करने के लिए एक चीज है, यदि आप इसे सेट $ErrorActionPreferenceकरते हैं"Stop" और इसका उपयोग करते हैं तो Write-Errorयह एक समाप्ति त्रुटि पैदा करेगा ।

लिपि में आप हमें इस से जोड़ते हैं:

if ($url.Contains("http")) {
       $request = [System.Net.HttpWebRequest]::Create($url)
}
else {
       $URL_Format_Error = [string]"Connection protocol not specified. Recommended action: Try again using protocol (for example 'http://" + $url + "') instead. Function aborting..."
       Write-Error $URL_Format_Error
    return
   }

ऐसा लगता है कि उस फ़ंक्शन का लेखक उस फ़ंक्शन के निष्पादन को रोकना चाहता था और स्क्रीन पर एक त्रुटि संदेश प्रदर्शित करना चाहता था, लेकिन संपूर्ण स्क्रिप्ट को निष्पादित करना बंद नहीं करना चाहता था। स्क्रिप्ट लेखक का उपयोग किया जा सकता है, throwहालांकि इसका मतलब यह होगा कि आपको try/catchफ़ंक्शन को कॉल करते समय उपयोग करना होगा ।

returnवर्तमान दायरे से बाहर निकल जाएगा जो एक फ़ंक्शन, स्क्रिप्ट या स्क्रिप्ट ब्लॉक हो सकता है। यह सबसे अच्छा कोड के साथ सचित्र है:

# A foreach loop.
foreach ( $i in  (1..10) ) { Write-Host $i ; if ($i -eq 5) { return } }

# A for loop.
for ($i = 1; $i -le 10; $i++) { Write-Host $i ; if ($i -eq 5) { return } }

दोनों के लिए आउटपुट:

1
2
3
4
5

यहाँ एक गोत्र का उपयोग returnकिया जा रहा है ForEach-Object। यह प्रसंस्करण को नहीं तोड़ देगा जैसे कोई उम्मीद कर सकता है।

अधिक जानकारी:


ठीक है, इसलिए थ्रो सब कुछ रोक देगा, राइट-एरर + रिटर्न केवल वर्तमान फ़ंक्शन को रोक देगा।
बिल बैरी

@BillBarry मैंने अपने उत्तर को एक स्पष्टीकरण के साथ थोड़ा अद्यतन किया return
एंडी अरिस्मेंडी

ओएस में वापस आए उचित त्रुटि कोड को सुनिश्चित करने के लिए निकास (1) के बाद लिखी गई त्रुटि के बारे में क्या? क्या यह कभी उचित है?
पब्रम

19

PowerShell में राइट-एरर cmdlet और थ्रो कीवर्ड के बीच मुख्य अंतर यह है कि पूर्व केवल मानक त्रुटि स्ट्रीम (stderr) के लिए कुछ पाठ प्रिंट करता है , जबकि बाद वाला वास्तव में रनिंग कमांड या फ़ंक्शन के प्रसंस्करण को समाप्त करता है, जिसे तब नियंत्रित किया जाता है। कंसोल द्वारा त्रुटि के बारे में जानकारी भेजकर PowerShell द्वारा।

आप दिए गए उदाहरणों में दो के विभिन्न व्यवहार का निरीक्षण कर सकते हैं:

$URL_Format_Error = [string]"..."
Write-Error $URL_Format_Error
return

इस उदाहरण में returnकीवर्ड को स्क्रिप्ट के निष्पादन को स्पष्ट रूप से रोकने के लिए जोड़ा गया है क्योंकि त्रुटि संदेश कंसोल से बाहर भेजे जाने के बाद। दूसरे उदाहरण में, दूसरी ओर, returnकीवर्ड आवश्यक नहीं है, क्योंकि समाप्ति का अर्थ यह है कि throw:

$URL_Format_Error = New-Object System.FormatException "..."
Throw $URL_Format_Error

2
यदि आपके पास $ ErrorActionPreference = "Stop" है, तो लिखने-त्रुटि भी प्रक्रिया को समाप्त कर देगी।
माइकल फ्रीजिम

4
अच्छी जानकारी, लेकिन जबकि PowerShell की त्रुटि स्ट्रीम अन्य गोले में पाठ-आधारित stderr स्ट्रीम के अनुरूप है , जैसे कि सभी PowerShell स्ट्रीम में ऑब्जेक्ट्स होते हैं , अर्थात् उदाहरण, जो स्वचालित संग्रह में डिफ़ॉल्ट रूप से एकत्र किए जाते हैं ( जिसमें सबसे हाल की त्रुटि होती है)। यहां तक ​​कि अगर आप सिर्फ एक स्ट्रिंग के साथ उपयोग करते हैं , तो वह स्ट्रिंग एक उदाहरण में लिपटी हुई है । [System.Management.Automation.ErrorRecord]$Error$Error[0]Write-Error[System.Management.Automation.ErrorRecord]
mklement0

16

महत्वपूर्ण : 2 प्रकार की समाप्ति त्रुटियां हैं , जो वर्तमान में मदद करने वाले विषयों को दुर्भाग्य से स्वीकार करती हैं :

  • स्टेटमेंट- सिटिंग एरर, जैसा कि कुछ गैर-वसूली योग्य स्थितियों में cmdlets द्वारा रिपोर्ट किया गया है और ऐसे भावों में जिनमें .NET अपवाद / PS रनटाइम त्रुटि होती है; केवल विवरण समाप्त हो गया है, और स्क्रिप्ट निष्पादन डिफ़ॉल्ट रूप से जारी है

  • स्क्रिप्ट - त्रुटि त्रुटियों (अधिक सटीक रूप से: रनस्पेस-टर्मिनेटिंग ), या तोThrowत्रुटि कार्रवाई-प्राथमिकता / चर / पैरामीटर मान के माध्यम से अन्य त्रुटि प्रकारों में से एक को बढ़ाकर या ट्रिगर करकेStop
    जब तक पकड़ा नहीं जाता, वे वर्तमान रनस्पेस (थ्रेड) को समाप्त करते हैं; यही है, वे न केवल वर्तमान स्क्रिप्ट को समाप्त करते हैं, लेकिन इसके सभी कॉलर्स भी, यदि लागू हो)।

PowerShell की त्रुटि हैंडलिंग के व्यापक अवलोकन के लिए, यह GitHub दस्तावेज़ीकरण समस्या देखें

इस पद का शेष गैर-समाप्ति बनाम कथन-समापन त्रुटियों पर केंद्रित है ।


प्रश्न के मूल पर ध्यान केंद्रित करने के साथ मौजूदा सहायक उत्तरों को पूरक करने के लिए: आप यह कैसे चुनते हैं कि क्या एक बयान को समाप्त करना है या गैर-समाप्ति त्रुटि ?

Cmdlet त्रुटि रिपोर्टिंग में सहायक दिशानिर्देश शामिल हैं; मुझे एक व्यावहारिक सारांश का प्रयास करने दें :

गैर-समाप्ति त्रुटियों के पीछे सामान्य विचार बड़े इनपुट सेटों के "दोष-सहिष्णु" प्रसंस्करण की अनुमति देना है : इनपुट वस्तुओं के सबसेट को संसाधित करने में विफलता (डिफ़ॉल्ट रूप से) को पूरी तरह से लंबे समय तक चलने वाली - प्रक्रिया को निरस्त नहीं करना चाहिए , आपको त्रुटियों का निरीक्षण करने और बाद में केवल असफल वस्तुओं को पुन: प्रस्तुत करने की अनुमति देता है - जैसा कि स्वचालित चर में एकत्र त्रुटि रिकॉर्ड के माध्यम से बताया गया है $Error

  • यदि आपका cmdlet / उन्नत फ़ंक्शन: एक गैर- त्रुटि त्रुटि की रिपोर्ट करें:

    • पाइपलाइन इनपुट और / या सरणी-मूल्यवान मापदंडों के माध्यम से MULTIPLE इनपुट ऑब्जेक्ट को स्वीकार करता है , और
    • विशेष इनपुट ऑब्जेक्ट्स के लिए त्रुटियां होती हैं , और
    • इन त्रुटियों करें क्योंकि इससे आगे इनपुट के नहीं रोकने प्रसंस्करण वस्तुओं में सिद्धांत ( situationally , हो सकता है कोई इनपुट वस्तुओं छोड़ दिया और / या पिछले इनपुट वस्तुओं पहले से ही सफलतापूर्वक संसाधित कर दिया हो सकता है)।
      • उन्नत कार्यों में, $PSCmdlet.WriteError()एक गैर-समाप्ति त्रुटि की रिपोर्ट करने के लिए उपयोग करें ( Write-Errorदुर्भाग्य से, कॉलर के दायरे में $?सेट होने का कारण नहीं है - यह गीथहब समस्या देखें )।$False
      • हैंडलिंग एक गैर समाप्त त्रुटि: $?आपको बतलाता है कि हाल ही में आदेश सूचना कम से कम एक गैर समाप्त त्रुटि।
        • इस प्रकार, $?होने $Falseका मतलब यह भी हो सकता है कि इनपुट ऑब्जेक्ट्स के किसी भी (गैर-रिक्त) सबसेट को ठीक से संसाधित नहीं किया गया था, संभवतः संपूर्ण सेट।
        • वरीयता चर $ErrorActionPreferenceऔर / या सामान्य cmdlet पैरामीटर -ErrorActionत्रुटि आउटपुट व्यवहार के संदर्भ में गैर-समाप्ति त्रुटियों (केवल) के व्यवहार को संशोधित कर सकता है और क्या गैर-समाप्ति त्रुटियों को स्क्रिप्ट- अलग करने के लिए बढ़ाया जाना चाहिए ।
  • अन्य सभी मामलों में एक त्रुटि - त्रुटि की रिपोर्ट करें ।

    • विशेष रूप से, यदि कोई त्रुटि cmdlet / उन्नत फ़ंक्शन में होती है जो केवल एक SINGLE या NO इनपुट ऑब्जेक्ट को स्वीकार करता है और NO या SINGLE आउटपुट ऑब्जेक्ट को आउटपुट करता है या केवल पैरामीटर इनपुट लेता है और दिए गए पैरामीटर मान सार्थक संचालन को रोकते हैं।
      • उन्नत कार्यों में, आपको $PSCmdlet.ThrowTerminatingError()स्टेटमेंट-टर्मिनेशन त्रुटि उत्पन्न करने के लिए उपयोग करना चाहिए ।
      • ध्यान दें कि, इसके विपरीत, Throwकीवर्ड एक स्क्रिप्ट -त्रुटि उत्पन्न करता है जो संपूर्ण स्क्रिप्ट (तकनीकी रूप से: वर्तमान थ्रेड ) को निरस्त करता है ।
      • हैंडलिंग एक बयान-समाप्त त्रुटि: एक try/catchहैंडलर या trapबयान किया जा सकता है (जो नहीं कर सकते के साथ इस्तेमाल किया जा गैर समाप्त त्रुटियों), लेकिन टिप्पणी भी है कि बयान डिफ़ॉल्ट रूप से -terminating त्रुटियों चलने से स्क्रिप्ट के बाकी को रोकने नहीं है। साथ के रूप में गैर-सांत त्रुटियों, $?को दर्शाता है $False, तो पिछले बयान एक बयान-समाप्त त्रुटि शुरू हो गया।

अफसोस की बात है, PowerShell के सभी मुख्य cmdlets इन नियमों द्वारा नहीं खेलते हैं :

  • विफल होने की संभावना नहीं है, New-TemporaryFile(PSv5 +) एक गैर-समाप्ति त्रुटि की रिपोर्ट करेगा यदि यह विफल रहा, पाइपलाइन इनपुट को स्वीकार नहीं करने और केवल एक आउटपुट ऑब्जेक्ट का उत्पादन करने के बावजूद - इसे कम से कम पावरस्लैम [कोर] 7.0 के रूप में सही किया गया है, हालांकि: GitHub देखें मुद्दा

  • Resume-Jobमदद का दावा है कि एक असमर्थित नौकरी प्रकार (जैसे कि बनाई गई नौकरी के साथ Start-Job, जो समर्थित नहीं है, क्योंकि Resume-Jobकेवल वर्कफ़्लो नौकरियों पर लागू होता है ) को समाप्त करने का कारण बनता है, लेकिन यह PSv5.1 के रूप में सच नहीं है।


8

Write-Errorफ़ंक्शन के उपभोक्ता को -ErrorAction SilentlyContinue(वैकल्पिक रूप से -ea 0) के साथ त्रुटि संदेश को दबाने की अनुमति देता है । जबकि throwआवश्यकता हैtry{...} catch {..}

एक कोशिश का उपयोग करने के लिए ... के साथ पकड़ Write-Error:

try {
    SomeFunction -ErrorAction Stop
}
catch {
    DoSomething
}

यदि आप त्रुटि संदेश को दबाना चाहते हैं, तो आपको राइट-एरर कॉल करने की आवश्यकता क्यों है?
माइकल फ़्रीजिम

8

के अलावा एंडी Arismendi के जवाब :

चाहे राइट-त्रुटि प्रक्रिया समाप्त हो जाता है या नहीं पर निर्भर करता है $ErrorActionPreferenceसेटिंग।

गैर-तुच्छ लिपियों के लिए, तेजी से विफल होने के लिए $ErrorActionPreference = "Stop"एक अनुशंसित सेटिंग है।

"त्रुटियों के संबंध में PowerShell का डिफ़ॉल्ट व्यवहार, जो त्रुटि पर जारी है ... बहुत VB6 लगता है" त्रुटि फिर से शुरू करें "-ish"

( http://codebetter.com/jameskovacs/2010/02/25/the-exec-problem/ से )

हालाँकि, यह Write-Errorकॉल को समाप्त करता है।

अन्य पर्यावरण सेटिंग्स की परवाह किए बिना गैर-समाप्ति कमांड के रूप में राइट-एरर का उपयोग करने के लिए , आप मूल्य के साथ सामान्य पैरामीटर का उपयोग कर सकते हैं :-ErrorActionContinue

 Write-Error "Error Message" -ErrorAction:Continue

0

यदि आपका कोड पढ़ना सही है तो आप सही हैं। समाप्ति त्रुटियों का उपयोग करना चाहिए throw, और यदि आप .NET प्रकारों के साथ काम कर रहे हैं, तो यह .NET अपवाद सम्मेलनों का पालन करने के लिए भी उपयोगी है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.