2010-10-22 16 views
32

मुझे पता है कि BEGIN ब्लॉक को एक पर्ल प्रोग्राम के मुख्य निकाय से पहले संकलित और निष्पादित किया गया है। आप इस बात का यकीन है कि नहीं कर रहे हैं बस इस पर आदेश पर्ल -cw चलाने की कोशिश:पर्ल में BEGIN ब्लॉक की भूमिका क्या है?

#!/ms/dist/perl5/bin/perl5.8 

use strict; 
use warnings; 

BEGIN { 
    print "Hello from the BEGIN block\n"; 
} 

END { 
    print "Hello from the END block\n"; 
} 

मैं सिखाया गया है कि जल्दी संकलन और एक शुरू के निष्पादन ब्लॉक एक प्रोग्रामर यह सुनिश्चित करें कि कोई भी आवश्यक संसाधनों से पहले उपलब्ध हैं की सुविधा देता है मुख्य कार्यक्रम निष्पादित किया जाता है।

और इसलिए मैं यह सुनिश्चित करने के लिए BEGIN ब्लॉक का उपयोग कर रहा हूं कि डीबी कनेक्शन जैसी चीजें स्थापित की गई हैं और मुख्य कार्यक्रम द्वारा उपयोग के लिए उपलब्ध हैं। इसी प्रकार, मैं यह सुनिश्चित करने के लिए ईएनडी ब्लॉक का उपयोग करता हूं कि प्रोग्राम समाप्त होने से पहले सभी संसाधन बंद, हटाए गए, समाप्त हो जाएं।

आज सुबह एक चर्चा के बाद, मुझे आश्चर्य है कि क्या यह BEGIN और END ब्लॉक को देखने का गलत तरीका है।

पर्ल में एक BEGIN ब्लॉक की इच्छित भूमिका क्या है?

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

use strict; 
use warnings; 

my $x = 12; 

BEGIN { 
    $x = 14; 
} 

print "$x\n"; 

जब निष्पादित यह प्रिंट 12.

अद्यतन 2: इस नए संस्करण नीचे एरिक स्ट्रॉम की टिप्पणी के लिए धन्यवाद यह स्पष्ट करता है:

use strict; 
use warnings; 

my $x = 12; 
my $y; 

BEGIN { 
    $x = 14; 
    print "x => $x\n"; 
    $y = 16; 
    print "y => $y\n"; 
} 

print "x => $x\n"; 
print "y => $y\n"; 

और आउटपुट

x => 14 
y => 16 
x => 12 
y => 16 

चालू सीई फिर से, धन्यवाद एरिक!

+2

http://www.compuspec.net/reference/language/perl/BEGIN_and_END.shtml – jantimon

+0

अगर ऐसा है, तो क्यों मैं एक करने के लिए एक DBI संबंध नहीं बना सकते मानक डीबीआई कनेक्ट() फ़ंक्शन का उपयोग करते हुए एक BEGIN ब्लॉक के भीतर डीबी? अगर मैं BEGIN ब्लॉक को हटा देता हूं, तो कनेक्शन –

+6

आपके अपडेट के लिए बनाया गया है: ऐसा इसलिए है क्योंकि 'मेरा $ x = 12' परिवर्तनीय समय पर चर घोषित करता है लेकिन असाइनमेंट नहीं करता है। फिर स्टार्ट ब्लॉक चलता है जो 14 को असाइन करता है। फिर जब प्रोग्राम चलाना शुरू होता है, तो 'मेरी' लाइन का असाइनमेंट आपको 12 देता है। –

उत्तर

21

क्या आपने BEGIN{} ब्लॉक को INIT{} ब्लॉक के लिए स्वैप करने का प्रयास किया है? मॉडपरल जैसी चीजों के लिए यह मानक दृष्टिकोण है जो "संकलन-एक बार, रन-कई" मॉडल का उपयोग करते हैं, क्योंकि आपको प्रत्येक अलग-अलग रन पर चीजों को फिर से शुरू करने की आवश्यकता होती है, न केवल संकलन के दौरान।

लेकिन मुझे यह पूछना है कि यह सब कुछ विशेष ब्लॉक में क्यों है। आप कुछ प्रकार के prepare_db_connection() फ़ंक्शन क्यों नहीं बनाते हैं, और उसके बाद प्रोग्राम को शुरू होने पर आपको इसकी आवश्यकता होती है?

कुछ ऐसा जो BEGIN{} में काम नहीं करेगा, वही समस्या होगी यदि यह मॉड्यूल फ़ाइल में मुख्य-पंक्ति कोड है जो use डी प्राप्त करता है। INIT{} ब्लॉक का उपयोग करने का यह एक और संभावित कारण है।

मैं भी देखा है कि use के बजाय एक require, या एक BEGIN{} के बजाय एक INIT{} की तरह कुछ का उपयोग कर सुलझाया जा करने के लिए आपसी प्रत्यावर्तन की समस्याओं घातक-गले लगाओ। लेकिन यह बहुत दुर्लभ है।

इस कार्यक्रम पर विचार करें:

% cat sto-INIT-eg 
#!/usr/bin/perl -l 
print    " PRINT: main running"; 
die     " DIE: main dying\n"; 
die     "DIE XXX /* NOTREACHED */"; 
END   { print "1st END: done running" } 
CHECK  { print "1st CHECK: done compiling" } 
INIT  { print "1st INIT: started running" } 
END   { print "2nd END: done running" } 
BEGIN  { print "1st BEGIN: still compiling" } 
INIT  { print "2nd INIT: started running" } 
BEGIN  { print "2nd BEGIN: still compiling" } 
CHECK  { print "2nd CHECK: done compiling" } 
END   { print "3rd END: done running" } 

जब केवल संकलित, यह पैदा करता है:

% perl sto-INIT-eg 
1st BEGIN: still compiling 
2nd BEGIN: still compiling 
2nd CHECK: done compiling 
1st CHECK: done compiling 
1st INIT: started running 
2nd INIT: started running 
    PRINT: main running 
    DIE: main dying 
3rd END: done running 
2nd END: done running 
1st END: done running 

और:

% perl -c sto-INIT-eg 
1st BEGIN: still compiling 
2nd BEGIN: still compiling 
2nd CHECK: done compiling 
1st CHECK: done compiling 
sto-INIT-eg syntax OK 

जबकि जब संकलित और मार डाला, यह इस का उत्पादन खोलप्रति 255 के बाहर निकलने की रिपोर्ट करता है।

आपको इसकी आवश्यकता होने पर कनेक्शन होने की व्यवस्था करने में सक्षम होना चाहिए, भले ही BEGIN{} बहुत जल्दी साबित हो।

एचएम, बस याद किया गया। में DATA के साथ कुछ करने का कोई मौका नहीं है, है ना? यह तब तक स्थापित नहीं है जब तक दुभाषिया चलता है; यह कंपाइलर के लिए खुला नहीं है।

31

जबकि BEGIN और END ब्लॉक का वर्णन आपके द्वारा वर्णित किया जा सकता है, सामान्य उपयोग बाद के संकलन को प्रभावित करने वाले परिवर्तनों को करना है।

उदाहरण के लिए, use Module qw/a b c/; बयान वास्तव में मतलब है:

BEGIN { 
    require Module; 
    Module->import(qw/a b c/); 
} 

इसी तरह, सबरूटीन घोषणा sub name {...} वास्तव में है:

BEGIN { 
    *name = sub {...}; 
} 

के बाद से इन ब्लॉकों संकलन समय पर चलाए जा रहे हैं, सभी लाइनों संकलित कर रहे हैं कि एक ब्लॉक चलाने के बाद नई परिभाषाओं का उपयोग किया जाएगा जो BEGIN ब्लॉक किए गए हैं। इस प्रकार आप बिना ब्रांड्स के सबराउटिन को कॉल कर सकते हैं, या कैसे विभिन्न मॉड्यूल "दुनिया के तरीके को बदलते हैं"।

END ब्लॉक परिवर्तन है कि BEGIN ब्लॉक कर दिया है साफ करने के लिए इस्तेमाल किया जा सकता है लेकिन यह एक DESTROY विधि के साथ वस्तुओं का उपयोग करने के अधिक आम है।

यदि आप जिस राज्य को साफ करने की कोशिश कर रहे हैं वह एक डीबीआई कनेक्शन है, तो END ब्लॉक में ऐसा करना ठीक है। हालांकि कई कारणों से मैं BEGIN ब्लॉक में कनेक्शन नहीं बनाऊंगा। आमतौर पर संकलन समय पर कनेक्शन उपलब्ध होने की आवश्यकता नहीं होती है। संकलन समय पर किसी डेटाबेस से कनेक्ट करने जैसी कार्रवाइयां करने से आपके द्वारा उपयोग किए जाने वाले किसी भी संपादक को बहुत धीमा कर दिया जाएगा जिसमें सिंटैक्स जांच हो रही है (क्योंकि यह perl -c चलाता है)।

+0

धन्यवाद एरिक। मैं गैर-ओओ कार्यक्रम में ईएनडी ब्लॉक का उपयोग करने के बारे में अपने प्रश्न में एक चेतावनी जोड़ने के बारे में निश्चित नहीं था। –

3

जबकि अन्य उत्तर सही हैं, मैं यह भी जब पर्ल को -n या -p स्विच का उपयोग कर BEGIN और END ब्लॉक के प्रयोग का उल्लेख करना लायक हैं।

http://perldoc.perl.org/perlmod.html

आप पर्ल को -n और -p स्विच का उपयोग करते हैं से, से शुरू और समाप्त काम वे awk में करते हैं, एक पतित मामले के रूप में बस के रूप में।

-n स्विच के साथ अपरिचित उन लोगों के लिए, यह पर्ल बताता है के साथ कार्यक्रम रैप करने के लिए:

while (<>) { 
    ... # your program goes here 
} 

http://perldoc.perl.org/perlrun.html#Command-Switches यदि आप पर्ल स्विच के बारे में अधिक विशिष्ट जानकारी के बारे में रुचि रखते हैं।

एक उदाहरण -n स्विच के साथ BEGIN के उपयोग को प्रदर्शित करने के रूप में, यह पर्ल एक लाइनर ls आदेश की तर्ज विश्लेषण करता है:

ls | perl -ne 'BEGIN{$i = 1} print "$i: $_"; $i += 1;' 

इस मामले में, BEGIN -block आरंभ करने के लिए प्रयोग किया जाता है ls की लाइनों को संसाधित करने से पहले इसे 1 पर सेट करके परिवर्तनीय $i। इस उदाहरण होगा उत्पादन कुछ की तरह:

1: foo.txt 
2: bar.txt 
3: program.pl 
4: config.xml 
संबंधित मुद्दे