2012-07-26 13 views
5

मैं पर्ल के Safe मॉड्यूल से reval का उपयोग कर रहा हूं और मैं इसे चेतावनी उत्पन्न करने से रोकना चाहता हूं अगर स्ट्रिंग को निकाला जा सकता है तो पार्स नहीं किया जा सकता है (असल में, मैं इसे किसी भी चेतावनी उत्पन्न करने से रोकना चाहता हूं) ।"कोई चेतावनी नहीं;" एक सुरक्षित डिब्बे में

उदाहरण के लिए, निम्न कोड: में

use strict; use warnings; 
use Safe;  
use feature qw/say/; 
my $cft = Safe->new; 

my $x = $cft->reval(') 1'); 
my $y = $cft->reval('2' ); 
say "x: $x"; 
say "y: $y"; 

परिणाम:

Number found where operator expected at (eval 5) line 1, near ") 1" 
    (Missing operator before 1?) 
Use of uninitialized value $x in concatenation (.) or string at ./test line 12. 
x: 
y: 2 

क्या मैं प्राप्त करने के लिए कोशिश कर रहा हूँ है $ x = undef और $ y = 2, और कोई चेतावनी। मैंने "कोई चेतावनी नहीं डालने की कोशिश की;" एक नया दायरे के अंदर है, लेकिन यह Reval के भीतर से उत्पादित चेतावनी पर कोई प्रभाव नहीं है (हालांकि, के रूप में @DavidO से कहा, यह 'अप्रारंभीकृत मूल्य' चेतावनी चुप्पी):

use strict; use warnings; 
use Safe;  
use feature qw/say/; 
my $cft = Safe->new; 
{ 
    no warnings; 
    my $x = $cft->reval(') 1'); 
    my $y = $cft->reval('2' ); 
    say "x: $x"; 
    say "y: $y"; 
} 

मुझे लगता है कि किसी भी तरह लगता है सुरक्षित डिब्बे के अंदर 'कोई चेतावनी' नहीं होनी चाहिए, इसलिए मैंने "कोई चेतावनी" तैयार करने की भी कोशिश की; तार करने के लिए किया जा रहा eval'ed:

use strict; use warnings; 
use Safe; 
use feature qw/say/; 
my $cft = Safe->new; 
{ 
    my $x = $cft->reval('no warnings;' . ') 1'); 
    my $y = $cft->reval('no warnings;' . '2' ); 
    say "x: $x"; 
    say "y: $y"; 
} 

इस तरह Reval कोई चेतावनी जारी नहीं करता है, लेकिन दोनों चर undef हैं:

Use of uninitialized value $x in concatenation (.) or string at ./test line 10. 
x: 
Use of uninitialized value $y in concatenation (.) or string at ./test line 11. 
y: 

मैं और क्या करने की कोशिश करना नहीं जानते हैं, और मुझे आशा है कि कि समस्या का विवरण पर्याप्त स्पष्ट था।

+1

आपका दूसरा प्रयास वास्तव में पहले के समान आउटपुट का उत्पादन नहीं करता है। यह अभी भी "कंपाइलटाइम" त्रुटि उत्पन्न करता है (वास्तव में संकलन त्रुटि को पुन: संशोधित करता है), लेकिन आपके 'कहना' कथन में एक अनियमित मूल्य को इंटरपोल करने से संबंधित रनटाइम चेतावनी नहीं। तो आपने उपरोक्त अपने दूसरे स्निपेट में वास्तव में अपनी समस्या का आधा हल किया है (चेतावनी को घुमाया है)। दूसरा आधा (संकलन-समय त्रुटि को झुकाव) अधिक समस्याग्रस्त है। – DavidO

+0

हाँ, आप इसके बारे में सही हैं। मैंने यह भी ध्यान नहीं दिया क्योंकि यहां मेरी मुख्य चिंता वास्तव में पुनरुत्थान थी - अनियमित वैरिएबल चेतावनियां उदाहरण का संक्षिप्त रखने की कोशिश कर रही हैं। वैसे भी, मैंने इसे स्पष्ट करने के लिए पोस्ट को अपडेट किया है। धन्यवाद! – andrefs

उत्तर

4

यदि आप [email protected] चेक करते हैं तो आप देखेंगे कि $cft->reval('no warnings;' . ') 1'); विफल हुआ। 'require' trapped by operation mask at (eval 5) line 1.। दूसरे शब्दों में, सुरक्षित अपना काम कर रहा है और उस कोड को लाइब्रेरी लोड करने की कोशिश करने से रोक रहा है।

$cft->reval('BEGIN { warnings->unimport; }) 1'); काम करेगा, मान लीजिए कि डिब्बे के बाहर चेतावनियां पहले ही लोड हो चुकी हैं। हालांकि, यह समय त्रुटियों को संकलित शांत नहीं करेगा। eval के विपरीत, reval उन्हें इनके माध्यम से जाने देता है। STDERR को शांत करने की आमोन की तकनीक का उपयोग करें।

+0

एक दो टायर दृष्टिकोण सबसे अच्छा काम करता है। चेतावनी 'reval' के बाहर उत्पन्न की जा रही है, और उस व्यापक दायरे पर squelched किया जा सकता है। संकलन त्रुटि 'reval' के अंदर उत्पन्न की जा रही है, और काफी जिद्दी है। यह वह जगह है जहां एसटीडीईआरआर को पुनर्निर्देशित करना सबसे कम विकल्प है, इमो। (दूसरा विकल्प सुरक्षित डिब्बे के अंदर 'eval' को स्पष्ट रूप से अनुमति देने वाला है, लेकिन फिर सहेजें का उपयोग क्यों परेशान करें? :))। – DavidO

+0

हालांकि यह मजाकिया है; सुरक्षित डिब्बे के अंदर '' qr/[c-a]/'' निष्पादित करना, जो एक अमान्य रेगेक्स है जो संकलित होने के रूप में त्रुटि को फेंक देगा, सफलतापूर्वक पुनरुत्थान से फंस गया है। – DavidO

+0

उत्तरों के लिए धन्यवाद। @ आमोन की विधि मौन के लिए सबसे गंभीर पार्सिंग त्रुटियों का सबसे अच्छा विकल्प प्रतीत होता है। BEGIN {चेतावनियां-> unimport;} काम को प्रतीत होता है सिवाय इसके कि अगर आप स्पष्ट रूप से स्ट्रिंग में "foo" चेतावनी जैसे कुछ कहते हैं: P – andrefs

4

no warningsuse warnings प्रगामा उत्पन्न सभी चेतावनियों को दबा देता है। आप शायद strict ures को भी हटाना चाहते हैं। लेकिन गंभीर पार्सिंग त्रुटियां किसी भी तरह से पॉप अप हो जाएंगी।

आप STDERR के लिए किसी भी उत्पादन के बिना, चाहे कितना रोग किसी भी कोड, निष्पादित करने के लिए चाहते हैं, तो आप स्थानीय रूप से संकेत हैंडलर को संशोधित करना चाहिए:

{ 
    # I know what I'm doing! 
    local $SIG{__WARN__} = sub {}; # locally ignore any warnings 
    eval $code; # catches all "die" 
} 

या हम फिर से खोलना सकता STDERR/dev/null रहे हैं:

{ 
    # I know what I'm doing! 
    open my $oldSTDERR, '>&' \*STDERR or die; 
    close STDERR or die; 
    open STDERR, '>', '/dev/null' or die; 

    eval $code; 

    close STDERR or die; 
    open STDERR, '>&', $oldSTDERR or die; 
    close $oldSTDERR; 
} 
+1

लेकिन सुरक्षित डिब्बे के अंदर 'eval $ code' की अनुमति नहीं है। मुझे लगता है कि '$ SIG {}' हैंडलर को स्थापित करना भी निषिद्ध है (और अच्छे कारण के लिए)।'Reval' के बाहर' $ SIG {} 'हैंडलर सेट अप करना या तो प्रभावी नहीं होगा। मुझे लगता है कि पुनर्विक्रय कोड संकलित करते समय उत्पन्न त्रुटि के संबंध में एसटीडीईआरआर को रीडायरेक्ट करना शायद सबसे साफ क्लज है। सामान्य साधनों के माध्यम से चेतावनी को घुमाया जा सकता है, क्योंकि यह पुनरुत्थान के बाहर होता है। – DavidO

+0

@amon द्वारा प्रस्तावित पहला समाधान निम्न कोड में काम कर रहा है: सख्त उपयोग करें; चेतावनियों का प्रयोग करें; सुरक्षित उपयोग करें; सुविधा का उपयोग qw/say /; मेरा $ सीएफटी = सुरक्षित-> नया; { स्थानीय $ एसआईजी {__ WARN__} = उप {}; मेरा $ x = $ cft-> reval (') 1'); मेरा $ y = $ cft-> reval ('2'); "x: $ x" कहें; "वाई: $ वाई" कहें; } यह वही लगता है जो मैं ढूंढ रहा था, धन्यवाद! – andrefs

+0

@andrefs अगर यह उत्तर आपके लिए काम करता है, तो कृपया अपने प्रश्न को "बंद" के रूप में चिह्नित करने के लिए इस उत्तर को "स्वीकार करें"। – amon