📄 ch13.htm
字号:
<P>In an earlier section, "Example: Using the <TT>die()</TT>FuNCtion," you saw the following code snippet being used:<BLOCKQUOTE><PRE>$code = "chdir('/user/printer')";eval($code) or die("PROBLEM WITH LINE: $code\n$! , stopped");</PRE></BLOCKQUOTE><P>This program shows that <TT>eval()</TT>will execute a line of code that is inside a variable. You canuse this capability in many different ways besides simply trappingfatal errors. The program in Listing 13.2 presents a prompt andexecutes Perl code as you type it. Another way of looking at thisprogram is that it is an interactive Perl interpreter.<P><IMG SRC="pseudo.gif" BORDER=1 ALIGN=RIGHT><p><BLOCKQUOTE><I>Loop until the user enters </I><TT><I>exit</I></TT><I>.<BR>Print the prompt.<BR>Get a line of input from </I><TT><I>STDIN</I></TT><I>and remove the ending linefeed.<BR>Execute the line.<BR>If the executed code set the </I><TT><I>$@</I></TT><I>error message variable, display the error message as a warning.</I></BLOCKQUOTE><HR><BLOCKQUOTE><B>Listing 13.2 13LST02.PL-Using Perl Interactively<BR></B></BLOCKQUOTE><BLOCKQUOTE><PRE>do { print("> "); chop($_ = <>); eval($_); warn() if $@;} while ($_ ne "exit");</PRE></BLOCKQUOTE><HR><P>When you run this program, you will see a <TT>></TT>prompt. At the prompt, you can type in any Perl code. When youpress Enter, the line is executed. You can even define fuNCtionsyou can use later in the interactive session. The program canbe stopped by typing <TT>exit</TT>at the command line.<P>If you like powerful command-line environments, you can buildon this small program to create a personalized system. For example,you might need to perform a backup operation before leaving work.Instead of creating a batch file (under DOS) or a shell file (underUNIX), you can add a new command to the Perl interactive program,as in Listing 13.3.<P><IMG SRC="pseudo.gif" BORDER=1 ALIGN=RIGHT><p><BLOCKQUOTE><I>Loop until the user enters </I><TT><I>exit</I></TT><I>.<BR>Print the prompt.<BR>Get a line of input from </I><TT><I>STDIN</I></TT><I>and remove the ending linefeed.<BR>If the inputted line begins with </I><TT><I>do#</I></TT><I>,then a custom command has been entered.<BR>Process the </I><TT><I>do#backup</I></TT><I>custom command.<BR>See if the user needs help.<BR>Otherwise, use the </I><TT><I>eval()</I></TT><I>fuNCtion to execute the inputted line.<BR>If the executed code set the </I><TT><I>$@</I></TT><I>error message variable, display the error message as a warning.</I></BLOCKQUOTE><HR><BLOCKQUOTE><B>Listing 13.3 13LST03.PL-An Interactive Perl Interpreterthat Understands Custom Commands<BR></B></BLOCKQUOTE><BLOCKQUOTE><PRE>sub backItUp { '\backup /user/*'; 'delete /user/*.bak'}sub help { print("do#backup will perform the nightly backup\n"); print("help will display this message.\n\n");}do { print("> "); chop($_ = <>); if (/^do#/) { backItUp)() if /backup/; } elsif (/^\s*help/) { help(); } else { eval($_); warn() if $@; }} while ($_ ne "exit");</PRE></BLOCKQUOTE><HR><P>This program invokes the backup program and deletes the backupfiles if you enter <TT>do#backup</TT>at the <TT>></TT> prompt. Of course,you need to modify this program to perform the customized commandsyou'd like to have. This technique also enables you to centralizeyour administrative tasks, which will make them easier to documentand maintain.<BR><p><CENTER><TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%><TR><TD><B>Tip</B></TD></TR><TR><TD><BLOCKQUOTE>If you are running Perl on a DOS or Windows machine, consider replacing your small batch utility programs with one Perl interpreter and some customized commands. This saves on hard disk space if you use a lot of batch files because each file may take up to 4,096 bytes, regardless of its actual size.</BLOCKQUOTE></TD></TR></TABLE></CENTER><P><H2><A NAME="WhatIsaSignal"><FONT SIZE=5 COLOR=#FF0000>What Is a Signal?</FONT></A></H2><P><I>Signals</I> are messages sent by the operating system to theprocess running your Perl script. At any time, a signal that mustbe answered can be sent to your process. Normally, a default handleris used to take care of a signal. For example, under Windows 95,when you press the Ctrl+C key combination, your process is sentan <TT>INT</TT> or interrupt signal.The default handler responds by ending the process and displaysthe following message:<BLOCKQUOTE><PRE>^C at test.pl line 22</PRE></BLOCKQUOTE><P>Of course, the filename and line number change to match the particularsof whatever script happens to be running when Ctrl+C was pressed.The <TT>^C</TT> notation refers tothe Ctrl+C key sequeNCe.<H3><A NAME="ExampleHowtoHandleaSignal">Example: How to Handle a Signal</A></H3><P>You can cause Perl to ignore the Ctrl+C key sequeNCe by placingthe following line of code near the beginning of your program:<BLOCKQUOTE><PRE>$SIG{'INT'} = 'IGNORE';</PRE></BLOCKQUOTE><P>You can restore the default handler like this:<BLOCKQUOTE><PRE>$SIG{'INT'} = 'DEFAULT';</PRE></BLOCKQUOTE><P>If you need to ensure that files are closed, error messages arewritten, or other cleanup chores are completed, you need to createa custom <TT>INT</TT> handle fuNCtion.For example:<BLOCKQUOTE><PRE>sub INT_handler { # close all files. # send error message to log file. exit(0);}$SIG{'INT'} = 'INT_handler';</PRE></BLOCKQUOTE><P>If the Ctrl+C key sequeNCe is pressed anytime after the hash assignmentis made, the <TT>INT_handler</TT>fuNCtion is called instead of the default handler.<BR><p><CENTER><TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%><TR><TD><B>Note</B></TD></TR><TR><TD><BLOCKQUOTE>In theory, you could remove the <TT>exit()</TT> call from the signal handler fuNCtion, and the script should start executing from wherever it left off. However, this feature is not working on several platforms. If you want to test your platform, run the following small program:</BLOCKQUOTE><BLOCKQUOTE><TT>sub INT_handler {<BR> print("Don't Interrupt!\n");<BR>}<BR><BR>$SIG{'INT'} = 'INT_handler';<BR>for ($x = 0; $x < 10; $x++) {<BR> print("$x\n");<BR> sleep 1;<BR>}</TT></BLOCKQUOTE><BLOCKQUOTE>You should be able to press Ctrl+C while the script is counting without forcing the script to end.</BLOCKQUOTE></TD></TR></TABLE></CENTER><P><P>The <TT>%SIG</TT> associative arrayholds only entries you have created for your custom signal handlerfuNCtions. So, unfortunately, you can't find out which signalsare supported by looking at the array returned by <TT><I>keys</FONT></I><FONT FACE="Courier">(%SIG)</TT>.<BR><p><CENTER><TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%><TR><TD><B>Tip</B></TD></TR><TR><TD><BLOCKQUOTE>If you are running Perl on a UNIX machine, you can run the <TT>kill -l</TT> command. This command displays a list of possible signals.</BLOCKQUOTE></TD></TR></TABLE></CENTER><P><P>I looked directly into the perl.exe file supplied with my Perldistribution to find out that the hip port of Perl for Win32 supportsthe following signals:<BLOCKQUOTE><TT>ABRT2</TT>-This signal means thatanother process is trying to abort your process.</BLOCKQUOTE><BLOCKQUOTE><TT>BREAK2</TT>-This signal indicatesthat a Ctrl+Break key sequeNCe was pressed under Windows.</BLOCKQUOTE><BLOCKQUOTE><TT>TERM2</TT>-This signal means thatanother process is trying to terminate your process.</BLOCKQUOTE><BLOCKQUOTE><TT>SEGV2</TT>-This signal indicatesthat a segment violation has taken place.</BLOCKQUOTE><BLOCKQUOTE><TT>FPE2</TT>-This signal catchesfloating point exceptions.</BLOCKQUOTE><BLOCKQUOTE><TT>ILL2</TT>-This signal indicatesthat an illegal instruction has been attempted.</BLOCKQUOTE><BLOCKQUOTE><TT>INT2</TT>-This signal indicatesthat a Ctrl+C key sequeNCe was pressed under Windows.</BLOCKQUOTE><P>You can also use the <TT>%SIG</TT>hash to trap a call to the <TT>warn()</TT>and <TT>die()</TT> fuNCtions. Thiscomes in handy if you're working with someone else's code andwant to keep a log of whenever these fuNCtions are called. Ratherthan finding every place the fuNCtions are used, you can definea handler fuNCtion as in Listing 13.4.<P><IMG SRC="pseudo.gif" BORDER=1 ALIGN=RIGHT><p><BLOCKQUOTE><I>Define a handler for the </I><TT><I>warn()</I></TT><I>fuNCtion. The error message is passed to the handler as the firstelement of the </I><TT><I>@_ array</I></TT><I>.<BR>Define a handler for the </I><TT><I>die()</I></TT><I>fuNCtion.<BR>Define the </I><TT><I>sendToLogfile()</I></TT><I>utility fuNCtion.<BR>Start the signal catching by creating two entries in the </I><TT><I>%SIG</I></TT><I>hash.<BR>Invoke the </I><TT><I>warn()</I></TT><I>and </I><TT><I>die()</I></TT><I> fuNCtions.</I></BLOCKQUOTE><HR><BLOCKQUOTE><B>Listing 13.4 13LST04.PL-How to Define Signal HandlerFuNCtions for the </B><TT><I><B><FONT FACE="Courier">warn()</FONT></B></I></TT><B>and </B><TT><I><B><FONT FACE="Courier">die() </FONT></B></I></TT><B>FuNCtions<BR></B></BLOCKQUOTE><BLOCKQUOTE><PRE>sub WARN_handler { my($signal) = @_; sendToLogfile("WARN: $signal");}sub DIE_handler { my($signal) = @_; sendToLogfile("DIE: $signal");}sub sendToLogfile { my(@array) = @_; open(LOGFILE, ">>program.log"); print LOGFILE (@array); close(LOGFILE);}$SIG{__WARN__} = 'WARN_handler';$SIG{__DIE__} = 'DIE_handler';chdir('/printer') or warn($!);chdir('/printer') or die($!);</PRE></BLOCKQUOTE><HR><P>When this program is done executing, the <TT>PROGRAM.LOG</TT>file contains these lines:<BLOCKQUOTE><PRE>WARN: No such file or directory at 13lst02.pl line 22.DIE: No such file or directory at 13lst02.pl line 23.</PRE></BLOCKQUOTE><H2><A NAME="Summary"><FONT SIZE=5 COLOR=#FF0000>Summary</FONT></A></H2><P>Your program's capability to handle error conditions that mayarise will determine, to a certain extent, how usable your programis. If a user of your program finds that it stops working withno error messages and, therefore, no way to solve whatever problemhas arisen, then your program won't be used for long.<P>Displaying error messages is also valuable during the programmingand debugging stage. If you mistakenly type a directory name,it may take you an hour to look through the script and find theproblem. Handling the <TT>No such directory</TT>error correctly in the first place will tell you what the problemis and which line of the script has the problem.<P>In this chapter, you saw that checking for errors usually meanslooking at the return value of the fuNCtions that are called.Some fuNCtions set the <TT>errno</TT>variable while others simply return true or false. While the <TT>errno</TT>variable does have a core set of values that are system independent,it also has system-dependent values. Listing 13.1 showed you howto display the error values applicable to your system.<P>Next, you read about the <TT>or</TT>logical operator. This operator evaluates only the right operandif the left is false. Therefore, it is useful when testing forunsuccessful fuNCtions that return false upon failure.<P>The <TT>die()</TT> and <TT>warn()</TT>fuNCtions are both used to display an error message. In addition,the <TT>die()</TT> fuNCtion causesthe script to end.<P>Then, the <TT>eval()</TT> fuNCtionwas covered. It is used to execute Perl code in a protected environmentso that fatal errors will not end the script. Any error messagesthat do arise will be placed into the <TT>$@</TT>special variable. All variable value changes and fuNCtion definitionsaffect the main program.<P>Lastly, the signals were covered. Signals are messages sent toa process by the operating system. There is a wide range of signals,and they differ depending on which operating system you are using.The <TT>%SIG</TT> associative arrayis used to set up your own signal handling fuNCtion.<P>The next chapter discusses object orientation. You learn the definitionof an object, how to create one, and how to derive new objectsfrom existing objects.<H2><A NAME="ReviewQuestions"><FONT SIZE=5 COLOR=#FF0000>Review Questions</FONT></A></H2><P>Answers to Review Questions are in Appendix A.<OL><LI>Why is it important to check for errors?<LI>How is the <TT>die()</TT> fuNCtiondifferent from the <TT>warn()</TT>fuNCtion?<LI>What is the meaning of the <TT>$!</TT>special variable?<LI>What does the <TT>eval()</TT>fuNCtion do?<LI>What is a signal?<LI>What will the statement <TT>$SIG{'ABRT'}= 'IGNORE'</TT> do?<LI>Which signal is used to trap floating point exceptions?</OL><H2><A NAME="ReviewExercises"><FONT SIZE=5 COLOR=#FF0000>Review Exercises</FONT></A></H2><OL><LI>Write a program that opens a file and uses the <TT>die()</TT>fuNCtion if an error occurs.<LI>Write a program that uses the <TT>warn()</TT>fuNCtion if an existing file will be overwritten by an <TT>open()</TT>statement.<LI>List three situations where the <TT>warn()</TT>fuNCtion could be used.<LI>List three situations where the <TT>die()</TT>fuNCtion could be used.<LI>Modify the interactive Perl interpreter to print a versionnumber when the <TT>version</TT> customcommand is used.<LI>Modify the interactive Perl interpreter to save all commandsentered into a log file. Add a timestamp to each log entry.</OL><HR><CENTER><P><A HREF="ch12.htm"><IMG SRC="pc.gif" BORDER=0 HEIGHT=88 WIDTH=140></A><A HREF="#CONTENTS"><IMG SRC="cc.gif" BORDER=0 HEIGHT=88 WIDTH=140></A><A HREF="index.htm"><IMG SRC="hb.gif" BORDER=0 HEIGHT=88 WIDTH=140></A><A HREF="ch14.htm"><IMG SRC="nc.gif" BORDER=0 HEIGHT=88 WIDTH=140></A><HR WIDTH="100%"></P></CENTER></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -