锘??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲中文字幕久在线,亚洲老熟女五十路老熟女bbw,亚洲人成网亚洲欧洲无码http://m.tkk7.com/pyguru/category/494.htmlA blog of technology and life.zh-cnFri, 02 Mar 2007 01:59:37 GMTFri, 02 Mar 2007 01:59:37 GMT60Parsing MIME & HTMLhttp://m.tkk7.com/pyguru/archive/2005/02/19/1312.htmlpygurupyguruFri, 18 Feb 2005 16:33:00 GMThttp://m.tkk7.com/pyguru/archive/2005/02/19/1312.htmlhttp://m.tkk7.com/pyguru/comments/1312.htmlhttp://m.tkk7.com/pyguru/archive/2005/02/19/1312.html#Feedback0http://m.tkk7.com/pyguru/comments/commentRss/1312.htmlhttp://m.tkk7.com/pyguru/services/trackbacks/1312.html
Parsing MIME & HTML

Understanding an email message encoded with MIME can be very, very, very difficult. It can get frustrating due to the number of options and different ways to do the actual encoding. Now add to that the sometimes too-liberal interpretations of the relevant RFCs by the email client designers and you will begin to get the idea. This article will show you how this task can be laughably simple thanks to Perl's extensive bag of tricks, CPANno alt defined.

I started out with a simple and straightforward mission: Fetch an Email from a POP mailbox and display it in a 7-bit, text-only capable device. This article describes the different stages for a simple tool that accomplishes this task, written in Perl with a lot of help from CPAN modules. I hope this to be useful to other Perl folks who might have a similar mission. Let's discuss each part of this task in turn, as we read through mfetch, the script I prepared as an example. Keep in mind that TIMTOWTDI.

Setting up the script

The first thing, as you know, is loading up all of the modules I will be using. I'm sure you already know strict and warnings. We'll see how do we use the rest of the modules a bit later.

    1: #!/usr/bin/perl
2:
3: # This script is (c) 2002 Luis E. Mu帽oz, All Rights Reserved
4: # This code can be used under the same terms as Perl itself. It comes
5: # with absolutely NO WARRANTY. Use at your own risk.
6:
7: use strict;
8: use warnings;
9: use IO::File;
10: use Net::POP3;
11: use NetAddr::IP;
12: use Getopt::Std;
13: use MIME::Parser;
14: use HTML::Parser;
15: use Unicode::Map8;
16: use MIME::WordDecoder;
17:
18: use vars qw($opt_s $opt_u $opt_p $opt_m $wd $e $map);
19:
20: getopts('s:u:p:m:');
21:
22: usage_die("-s server is required\n") unless $opt_s;
23: usage_die("-u username is required\n") unless $opt_u;
24: usage_die("-p password is required\n") unless $opt_p;
25: usage_die("-m message is required\n") unless $opt_m;
26:
27: $opt_s = NetAddr::IP->new($opt_s)
28: or die "Cannot make sense of given server\n";

Note the lines 27 and 28, where I use NetAddr::IPno alt defined to convert whatever the user gave us through the -s option into an IP address. This is a very common use of this module, as its new() method will convert many common IP notations into an object I can later extract an IP address from. It will even perform a name resolution for us if required. So far, everything should look familiar, as a lot of scripts start like this one.

It is worth noting that the error handling in lines 22-25 is not a brilliant example of good coding or documentation. It is much better practice to write your scripts' documentation in POD, and use a module such as Pod::Usageno alt defined to provide useful error messages to the user. At the very least, try to provide an informative usage message. You can see the usage_die() function if you download the complete script.

Fetching a message via POP3

On to deeper waters. The first step in parsing a message, is getting at the message itself. For this, I'll use Net::POP3no alt defined, which implements the POP3 protocol described in RFC-1939no alt defined. This is all done in the code below.

   30: my $pops = Net::POP3->new($opt_s->addr)
31: or die "Failed to connect to POP3 server: $!\n";
32:
33: $pops->login($opt_u, $opt_p)
34: or die "Authentication failed\n";
35:
36: my $fh = new_tmpfile IO::File
37: or die "Cannot create temporary file: $!\n";
38:
39: $pops->get($opt_m, $fh)
40: or die "No such message $opt_m\n";
41:
42: $pops->quit();
43: $pops = undef;
44:
45: $fh->seek(0, SEEK_SET);

At line 30, a connection to the POP server is attempted. This is a TCP connection, in this case to port 110. If this connection succeeds, the USER and PASS commands are issued at line 33, which are the simplest form of authentication supported by the POP protocol. Your username and password are being sent here through the network without the protection of cryptography, so a bit of caution is in order.

Net::POP3no alt defined supports many operations defined in the POP protocol that allow for more complex actions, such as fetching the list of messages, unseen messages, etc. It can also fetch messages for us in a variety of ways. Since I want this script to be as lightweight as possible (i.e., to burn as little memory as possible), I want to fetch the message to a temporary on-disk file. The temporary file is nicely provided by the new_tmpfile method of IO::Fileno alt defined in line 36, which returns a file handle to a deleted file. I can work on this file, which will magically disappear when the script is finished.

Later, I instruct the Net::POP3 object to fetch the required message from the mail server and write it to the supplied filehandle using the get method, on line 39. After this, the connection is terminated gracefully by invoking quit and destroying the object. Destroying the object insures that the TCP connection with the server is terminated, freeing the resources being held in the POP server as soon as possible. This is a good programming practice for network clients.

The interaction required by mfetch with the POP server is really simple, so I'm not making justice to Net::POP3. It provides a very complete implementation of the protocol, allowing for much more sophisticated applications.

Note that in line 45, I rewind the file so that the fetched message can be read back by the code that follows.

For this particular example, we could also have used Net::POP3Client, which provides a somewhat similar interface. The code would have looked more or less like the following fragment.

    1: my $pops = new Net::POP3Client(USER => $opt_u,
2: PASSWORD => $opt_p,
3: HOST => $opt_s->addr)
4: or die "Error connecting or logging in: $!\n";
5:
6: my $fh = new_tmpfile IO::File
7: or die "Cannot create temporary file: $!\n";
8:
9: $pops->HeadAndBodyToFile($fh, $opt_m)
10: or die "Cannot fetch message: $!\n";
11:
12: $pops->Close();

Parsing the MIME structure

Just as email travels inside a sort of envelope (the headers), complex messages that include attachments and generally, HTML messages, travel within a collection of MIME entities. You can think of these entities as containers that can transfer any kind of binary information through the Email infrastructure, which in general does not know how to deal with 8-bit data. The code reproduced below, takes care of parsing this MIME structure.

   47: my $mp = new MIME::Parser;
48: $mp->ignore_errors(1);
49: $mp->extract_uuencode(1);
50:
51: eval { $e = $mp->parse($fh); };
52: my $error = ($@ || $mp->last_error);
53:
54: if ($error)
55: {
56: $mp->filer->purge; # Get rid of the temp files
57: die "Error parsing the message: $error\n";
58: }

Perl has a wonderful class that provides the ability to understand this MIME encapsulation, returning a nice hierarchy of objects that represent the message. You access this facilities through the MIME::Parserno alt defined class, part of the MIME-Toolsno alt defined bundle. MIME::Parser returns a hierarchy of MIME::Entity objects representing your message. The parser is so smart, that if you pass it a non-MIME email, it will be returned to you as a text/plain entity.

MIME::Parser can be tweaked in many ways, as its documentation will show you. One of the points where this toggling might be important, is the decoding process. Remember that I need to be as light in memory usage as possible. The default behavior of MIME::Parser involves the use of temporary files for decoding of the message. These temporary files can be spared and core memory used instead by invoking output_to_core(). Before doing this, note all the caveats cited in the module's documentation. The most important one is that if a 100 MB file ends up in your inbox, this whole thing needs to be slurped into RAM.

In line 47 I create the parser object. The call to ignore_errors() in line 48 is an attempt to made this parser as tolerant as possible. extract_uuencode() in line 49, takes care of pieces of the email that are uu-encoded automatically, translating them back into a more readable form. The actual request to parse the message, available through reading the $fh filehandle, is in line 51. Note that it is enclosed in an eval block. I have to do this as the parser might throw an exception if certain errors are encountered. The eval allows me to catch this exception and react in a way that is sensible to this application. In this case, I want to be sure that any temporary file created by the parsing process is cleared by a call to purge(), as seen in lines 56 and 57.

Setting up the HTML parser

Parsing HTML can be a tricky and tedious task. Thankfully, Perl has a number of nice ways to help you do this job. A number of excellent books such as The Perl Cookbook (from O'Reilly & Associatesno alt defined) has a couple of recipes that came very close to what I needed, especially recipe 20.5, "Converting HTML to ASCII", which I reproduce below.

    1: use HTML::TreeBuilder;
2: use HTML::FormatText;
3:
4: $html = HTML::TreeBuilder->new();
5: $html->parse($document);
6:
7: $formatter = HTML::FormatText->new(leftmargin => 0, rightmargin => 50);
8:
9: $ascii = $formatter->format($html);

I did not want to use this recipe because of two reasons: I needed fine-grained control in the HTML to ASCII conversion and I wanted to have as little impact as possible in resources. I did a small benchmark that shows the kind of performance difference among the two options while parsing a copy of one of my web articles. The result below shows that the custom parser explained later runs faster than the Cookbook's recipe. This does not mean that the recipe or the modules it uses are bad. This result simply means that the recipe is actually doing a lot of additional work, which just happens to not be all that useful for this particular task.

bash-2.05a$ ./mbench
Benchmark: timing 100 iterations of Cookbook's, Custom...
Cookbook's: 73 wallclock secs (52.82 usr + 0.00 sys = 52.82 CPU) @ 1.89/s (n=100)
Custom: 1 wallclock secs ( 1.17 usr + 0.00 sys = 1.17 CPU) @ 85.47/s (n=100)
Rate Cookbook's Custom
Cookbook's 1.89/s -- -98%
Custom 85.5/s 4415% --

HTML::FormatTextno alt defined does an awesome job of converting the HTML to plain text. Unfortunately I have a set of guidelines that I need to follow in the conversion and that are not compatible with the output of this module. Additionally, HTML::TreeBuilderno alt defined does an excellent job of parsing an HTML document, but produces an intermediate structure - the parse tree - that in my case, wastes resources.

However, Perl has an excellent HTML parser in the HTML::Parserno alt defined module. In this case, I chose to use this class to implement an event-driven parser, where tokens (syntactic elements) in the source document cause the parser to call functions I provide. This allowed me complete control on the translation while sparing the intermediate data structure.

Converting HTML to text is a lossy transformation. This means that what goes out of this transformation is not exactly equivalent to what went in in the first place. Pictures, text layout, style and a few other information elements are lost. My needs required that I noted the existence of images as well as a reasonably accurate rendition of the page's text, but nothing else. Remember that the target device can only display 7-bit text, and this is within a very small and limited display. This piece of code sets up the parser to do what I need.

   62: my $parser = HTML::Parser->new
63: (
64: api_version => 3,
65: default_h => [ "" ],
66: start_h => [ sub { print "[IMG ",
67: d($_[1]->{alt}) || $_[1]->{src},"]\n"
68: if $_[0] eq 'img';
69: }, "tagname, attr" ],
70: text_h => [ sub { print d(shift); }, "dtext" ],
71: ) or die "Cannot create HTML parser\n";
72:
73: $parser->ignore_elements(qw(script style));
74: $parser->strict_comment(1);

Starting on line 71, I set up the HTML::Parser object that will help me do this. First, I tell it I want to use the latest (as of this writing) interface style, which provides more flexibility than earlier interfaces. On line 65, I tell the object that by default, no parse events should do anything. There are other ways to say this, but the one shown is the most efficient.

Lines 66 through 69 define a handler for the start events. This handler will be called each time an opening tag such as <a> or <img> is recognized in the source being parsed. Handlers are specified as a reference to an array whose first element tells the parser what to do and its second element, tells the parser what information to pass to the code. In this example, I supply a function that for any img tag, will output a hopefully descriptive text composed with either the alt or the src attributes. I request this handler to be called with the name of the tag as the first argument and the list of attributes as further arguments, through the string "tagname, attr" found in line 69. The d() function will be explained a bit later, but it has to do with decoding its argument.

The text event will be triggered by anything inside tags in the input text. I've set up a simpler handler for this event that merely prints out whatever is recognized. I also request that HTML entities such as &euro; or &ntilde; be decoded for me through the string "dtext" on line 70. HTML entities are used to represent special characters outside the traditional ASCII range. In the interest of document accuracy, you should always use entities instead of directly placing 8-bit characters in the text.

Some syntactic elements are used to enclose information that is not important for this application, such as <style>...</style> and <script>...</script>. I ask the parser to ignore those elements with the call to ignore_elements() at line 73. I also request the parser to follow strict comment syntax through the call to strict_comment() on line 74.

Setting up the Unicode mappings

MIME defines various ways to encode binary data depending on the frequency of octets greater than 127. With relatively few high-bit octets, Quoted-Printable encoding is used. When many high-bit octets are present, Base-64 encoding is used instead. The reason is that Quoted-Printable is slightly more readable but very inefficient in space while Base-64 is completely unreadable by standard humans and adds much less overhead in the size of encoded files. Often, message headers such as the sender's name are encoded using Quoted-Printable when they contain characters such as a '帽'. These headers look like From: =?ISO-8859-1?Q?Luis_Mu=F1oz?= <some@body.org> and should be converted to From: Luis Mu帽oz <some@body.org>. In plain english, Quoted-Printable encoding is being used to make the extended ISO-8859-1 characters acceptable for any 7-bit transport such as email. Many contemporary mail transport agents can properly handle message bodies that contain high-bit octets but will choke on headers with binary data, in case you were wondering why all this fuzz.

Lines 92 through 102 define setup_decoder(), which can use the headers contained in a MIME::Headno alt defined object to setup a suitable decoder based on the MIME::WordDecoderno alt defined class. This will translate instances of Quoted-Printable text, to its high-bit equivalent. Note that I selected ISO-8859-1 as the default in case no proper character set can be identified. This was a sensible choice for me, as ISO-8859-1 encloses spanish characters, which happen to be my native language.

   92: sub setup_decoder
93: {
94: my $head = shift;
95: if ($head->get('Content-Type')
96: and $head->get('Content-Type') =~ m!charset="([^\"]+)"!)
97: {
98: $wd = supported MIME::WordDecoder uc $1;
99: }
100: $wd = supported MIME::WordDecoder "ISO-8859-1" unless $wd;
101: }

But this clever decoding is not enough. Getting at the original high-bit characters is not enough. I must recode these high characters into something usable by the 7-bit display device. So in line 76 I set up a mapping based on Unicode::Map8no alt defined. This module can convert 8-bit characters such as ISO-8859-1 or ASCII into wider characters (Unicodeno alt defined) and then back into our chosen representation, ASCII, which only defines 7-bit characters. This means that any character that cannot be properly represented, will be lost, which for our application is acceptable.

   76: $map = Unicode::Map8->new('ASCII')
77: or die "Cannot create character map\n";

The decoding and character mapping is then brought together at line 90, where I define the d() function, that simply invokes the adequate MIME decoding method, transforms the resulting string into Unicode via the to16() method and then, transforms it back into ASCII using to8() to insure printable results in our device. Since I am allergic to warnings related to undef values, I make sure that decode() always get a defined string to work with.

   90: sub d { $map->to8($map->to16($wd->decode(shift||''))); }

As you might notice if you try this code, the conversion is again lossy because there are characters that does not exist in ASCII. You can experiment with the addpair() method to Unicode::Map8 in order to add custom character transformations (i.e., '鈧? might be 'E'). Another way to achieve this, is through deriving a class from Unicode::Map8 and implementing the unmapped_to8 method to supply your own interpretation of the missing characters. Take a look at the module's documentation for more information.

Starting the decode process

With all the pieces in place, all that's left is to traverse the hierarchy of entities that MIME::Parser provides after parsing a message. I implemented a very simple recursive function decode_entities starting at line 103. This is a recursive function because recursion comes naturally as a way to handle trees such as those produced by MIME::Parser. At least to me.

  103: sub decode_entities
104: {
105: my $ent = shift;
106:
107: if (my @parts = $ent->parts)
108: {
109: decode_entities($_) for @parts;
110: }
111: elsif (my $body = $ent->bodyhandle)
112: {
113: my $type = $ent->head->mime_type;
114:
115: setup_decoder($ent->head);
116:
117: if ($type eq 'text/plain')
118: { print d($body->as_string); }
119: elsif ($type eq 'text/html')
120: { $parser->parse($body->as_string); }
121: else
122: { print "[Unhandled part of type $type]"; }
123: }
124: }

The condition at line 107 asks if this part or entity contains other parts. If it does, it extracts them and invokes itself recursively to process each sub-part at line 109.

If this part is a leaf, its body is processed. Line 111 gets it as a MIME::Bodyno alt defined object. On line 155 I setup a decoder for this part's encoding and based on the type of this part, taken at line 113, the code on lines 117 to 122 call the proper handlers.

In order to fire the decoding process, I call decode_entities() with the result of the MIME decoding of the message on line 86. This will invoke the HTML parser when needed and in general, produce the output I look for in this example. After this processing is done, I make sure to wipe temporary files created by MIME::Parser on line 88. Note that if the message is not actually encoded with MIME, MIME::Parser will arrange for you to receive a single part of type text/plain that contains the whole message text, which is perfect for our application.

   86: decode_entities($e);
87:
88: $mp->filer->purge;

And that's about it

After these less than 130 lines of code, I can easily fetch and decode a message, such as in the following example:

bash-2.05a$ ./mfetch -s pop.foo.bar -u myself \
-p very_secure_password -m 5

Date: Sat, 28 Dec 2002 20:14:37 -0400
From: root <root@foo.bar>
To: myself@foo.bar
Subject: This is the plain subject

This is a boring and plain message.

More complex MIME messages can also be decoded. Look at this example where I dissect a dreaded piece of junk mail, but don't worry. I used head to spare you pages and pages of worthless image links:

bash-2.05a$ ./mfetch -s pop.foo.bar -u myself \
-p very_secure_password -m 2 | head -20


Date: Sun, 22 Dec 2002 23:22:25 -0400
From: Luis Muoz <lem@foo.bar>
To: Myself <myself@foo.bar>
Subject: Fwd: Get $860 Free - Come, Play, Have Fun!



Begin forwarded message:

> From: Cosmic Offers <munged@migada.com.INVALID>;
> Date: Sun Dec 22, 2002 20:59:43 America/Caracas
> To: spam@victim.net
> Subject: Get $860 Free - Come, Play, Have Fun!
>

>
[IMG http://www.migada.com/email/Flc_600_550_liberty_mailer_.gif]
[IMG http://www.migada.com/email/Flc_600_550_liberty_mail-02.gif]
[IMG http://www.migada.com/email/Flc_600_550_liberty_mail-03.gif]
[IMG http://www.migada.com/email/Flc_600_550_liberty_mail-04.gif]

If you're curious, please download the complete script and play with it a bit. I hope this tutorial and its related script to be as helpful for you as it has been for me



pyguru 2005-02-19 00:33 鍙戣〃璇勮
]]>
CGI::Carp - CGI routines for writing to the HTTPD (or other) error loghttp://m.tkk7.com/pyguru/archive/2005/02/18/1293.htmlpygurupyguruThu, 17 Feb 2005 21:27:00 GMThttp://m.tkk7.com/pyguru/archive/2005/02/18/1293.htmlhttp://m.tkk7.com/pyguru/comments/1293.htmlhttp://m.tkk7.com/pyguru/archive/2005/02/18/1293.html#Feedback0http://m.tkk7.com/pyguru/comments/commentRss/1293.htmlhttp://m.tkk7.com/pyguru/services/trackbacks/1293.html

NAME

CGI::Carp - CGI routines for writing to the HTTPD (or other) error log


SYNOPSIS

    use CGI::Carp;

    croak "We're outta here!";
confess "It was my fault: $!";
carp "It was your fault!";
warn "I'm confused";
die "I'm dying.\n";


DESCRIPTION

CGI scripts have a nasty habit of leaving warning messages in the error logs that are neither time stamped nor fully identified. Tracking down the script that caused the error is a pain. This fixes that. Replace the usual

    use Carp;

with

    use CGI::Carp

And the standard warn(), die (), croak(), confess() and carp() calls will automagically be replaced with functions that write out nicely time-stamped messages to the HTTP server error log.

For example:

   [Fri Nov 17 21:40:43 1995] test.pl: I'm confused at test.pl line 3.
[Fri Nov 17 21:40:43 1995] test.pl: Got an error message: Permission denied.
[Fri Nov 17 21:40:43 1995] test.pl: I'm dying.


REDIRECTING ERROR MESSAGES

By default, error messages are sent to STDERR. Most HTTPD servers direct STDERR to the server's error log. Some applications may wish to keep private error logs, distinct from the server's error log, or they may wish to direct error messages to STDOUT so that the browser will receive them.

The carpout() function is provided for this purpose. Since carpout() is not exported by default, you must import it explicitly by saying

   use CGI::Carp qw(carpout);

The carpout() function requires one argument, which should be a reference to an open filehandle for writing errors. It should be called in a BEGIN block at the top of the CGI application so that compiler errors will be caught. Example:

   BEGIN {
use CGI::Carp qw(carpout);
open(LOG, ">>/usr/local/cgi-logs/mycgi-log") or
die("Unable to open mycgi-log: $!\n");
carpout(LOG);
}

carpout() does not handle file locking on the log for you at this point.

The real STDERR is not closed -- it is moved to SAVEERR. Some servers, when dealing with CGI scripts, close their connection to the browser when the script closes STDOUT and STDERR. SAVEERR is used to prevent this from happening prematurely.

You can pass filehandles to carpout() in a variety of ways. The ``correct'' way according to Tom Christiansen is to pass a reference to a filehandle GLOB:

    carpout(\*LOG);

This looks weird to mere mortals however, so the following syntaxes are accepted as well:

    carpout(LOG);
carpout(main::LOG);
carpout(main'LOG);
carpout(\LOG);
carpout(\'main::LOG');

    ... and so on

FileHandle and other objects work as well.

Use of carpout() is not great for performance, so it is recommended for debugging purposes or for moderate-use applications. A future version of this module may delay redirecting STDERR until one of the CGI::Carp methods is called to prevent the performance hit.


MAKING PERL ERRORS APPEAR IN THE BROWSER WINDOW

If you want to send fatal (die, confess) errors to the browser, ask to import the special ``fatalsToBrowser'' subroutine:

    use CGI::Carp qw(fatalsToBrowser);
die "Bad error here";

Fatal errors will now be echoed to the browser as well as to the log. CGI::Carp arranges to send a minimal HTTP header to the browser so that even errors that occur in the early compile phase will be seen. Nonfatal errors will still be directed to the log file only (unless redirected with carpout).


By default, the software error message is followed by a note to contact the Webmaster by e-mail with the time and date of the error. If this message is not to your liking, you can change it using the set_message() routine. This is not imported by default; you should import it on the use() line:

    use CGI::Carp qw(fatalsToBrowser set_message);
set_message("It's not a bug, it's a feature!");

You may also pass in a code reference in order to create a custom error message. At run time, your code will be called with the text of the error message that caused the script to die. Example:

    use CGI::Carp qw(fatalsToBrowser set_message);
BEGIN {
sub handle_errors {
my $msg = shift;
print "<h1>Oh gosh</h1>";
print "Got an error: $msg";
}
set_message(\&handle_errors);
}

In order to correctly intercept compile-time errors, you should call set_message() from within a BEGIN{} block.


CHANGE LOG

1.05 carpout() added and minor corrections by Marc Hedlund <hedlund@best.com> on 11/26/95.

1.06 fatalsToBrowser() no longer aborts for fatal errors within eval() statements.

1.08 set_message() added and carpout() expanded to allow for FileHandle objects.

1.09 set_message() now allows users to pass a code REFERENCE for really custom error messages. croak and carp are now exported by default. Thanks to Gunther Birznieks for the patches.

1.10 Patch from Chris Dean (ctdean@cogit.com) to allow module to run correctly under mod_perl.


AUTHORS

Lincoln D. Stein <lstein@genome.wi.mit.edu> Feel free to redistribute this under the Perl Artistic License.


SEE ALSO

Carp, CGI::Base, CGI::BasePlus, CGI::Request, CGI::MiniSvr, CGI::Form, CGI::Response


DISCLAIMER

We are painfully aware that these documents may contain incorrect links and misformatted HTML. Such bugs lie in the automatic translation process that automatically created the hundreds and hundreds of separate documents that you find here. Please do not report link or formatting bugs, because we cannot fix per-document problems. The only bug reports that will help us are those that supply working patches to the installhtml or pod2html programs, or to the Pod::HTML module itself, for which I and the entire Perl community will shower you with thanks and praises.

If rather than formatting bugs, you encounter substantive content errors in these documents, such as mistakes in the explanations or code, please use the perlbug utility included with the Perl distribution.

--Tom Christiansen, Perl Documentation Compiler and Editor


Return to the Perl Documentation Index.
Return to the Perl Home Page.

pyguru 2005-02-18 05:27 鍙戣〃璇勮
]]>
Perl 5 by Examplehttp://m.tkk7.com/pyguru/archive/2005/02/18/1292.htmlpygurupyguruThu, 17 Feb 2005 19:56:00 GMThttp://m.tkk7.com/pyguru/archive/2005/02/18/1292.htmlhttp://m.tkk7.com/pyguru/comments/1292.htmlhttp://m.tkk7.com/pyguru/archive/2005/02/18/1292.html#Feedback0http://m.tkk7.com/pyguru/comments/commentRss/1292.htmlhttp://m.tkk7.com/pyguru/services/trackbacks/1292.html闃呰鍏ㄦ枃

pyguru 2005-02-18 03:56 鍙戣〃璇勮
]]>
Perl: The Carp Modulehttp://m.tkk7.com/pyguru/archive/2005/02/18/1291.htmlpygurupyguruThu, 17 Feb 2005 19:49:00 GMThttp://m.tkk7.com/pyguru/archive/2005/02/18/1291.htmlhttp://m.tkk7.com/pyguru/comments/1291.htmlhttp://m.tkk7.com/pyguru/archive/2005/02/18/1291.html#Feedback0http://m.tkk7.com/pyguru/comments/commentRss/1291.htmlhttp://m.tkk7.com/pyguru/services/trackbacks/1291.html Example: The Carp Module

This useful little module lets you do a better job of analyzing runtime errors-like when your script can't open a file or when an unexpected input value is found. It defines the carp(), croak(), and confess() fuNCtions. These are similar to warn() and die(). However, instead of reported in the exact script line where the error occurred, the fuNCtions in this module will display the line number that called the fuNCtion that generated the error. Confused? So was I, until I did some experimenting. The results of that experimenting can be found in Listing 15.6.

Load the Carp module.
Invoke the strict pragma.
Start the Foo namespace.
Define the
foo() fuNCtion.
Call the
carp() fuNCtion.
Call the
croak() fuNCtion.
Switch to the main namespace.
Call the
foo() fuNCtion.

Listing 15.6  15LST06.PL-Using the carp() and croak() from the Carp Module
use Carp;
use strict;

package Foo;
sub foo {
main::carp("carp called at line " . __LINE__ .
",\n but foo() was called");

main::croak("croak called at line " . __LINE__ .
",\n but foo() was called");
}

package main;
foo::foo();


This program displays:

carp called at line 9, 

but foo() was called at e.pl line 18

croak called at line 10,

but foo() was called at e.pl line 18

This example uses a compiler symbol, __LINE__, to iNCorporate the current line number in the string passed to both carp() and croak(). This technique enables you to see both the line number where carp() and croak() were called and the line number where foo() was called.

The Carp module also defines a confess() fuNCtion which is similar to croak() except that a fuNCtion call history will also be displayed. Listing 15.7 shows how this fuNCtion can be used. The fuNCtion declarations were placed after the foo() fuNCtion call so that the program flow reads from top to bottom with no jumping around.

Load the Carp module.
Invoke the strict pragma.
Call
foo().
Define
foo().
Call
bar().
Define
bar().
Call
baz().
Define
baz().
Call
Confess().

Listing 15.7  15LST07.PL-Using confess() from the Carp Module
use Carp;
use strict;

foo();

sub foo {
bar();
}

sub bar {
baz();
}

sub baz {
confess("I give up!");
}

This program displays:

I give up! at e.pl line 16

main::baz called at e.pl line 12

main::bar called at e.pl line 8

main::foo called at e.pl line 5

This daisy-chain of fuNCtion calls was done to show you how the fuNCtion call history looks when displayed. The fuNCtion call history is also called a stack trace. As each fuNCtion is called, the address from which it is called gets placed on a stack. When the confess() fuNCtion is called, the stack is unwound or read. This lets Perl print the fuNCtion call history.



pyguru 2005-02-18 03:49 鍙戣〃璇勮
]]>
主站蜘蛛池模板: 亚洲日韩乱码中文无码蜜桃臀网站 | 国产麻豆一精品一AV一免费| 亚洲成AV人片在| 最近中文字幕免费完整| 亚洲色精品VR一区区三区 | 在线播放免费人成毛片乱码| 亚洲国产精品人久久电影| 免费一级黄色毛片| 久久免费看少妇高潮V片特黄| 亚洲精品无码久久久久YW| 亚洲成在人线av| 亚洲AV日韩AV永久无码绿巨人 | 热re99久久6国产精品免费| 国产偷国产偷亚洲清高APP| 亚洲综合图色40p| 亚洲免费综合色在线视频| 一区二区在线视频免费观看| 亚洲国产成人精品无码一区二区| 亚洲国产精品一区二区九九| 亚洲免费一级视频| 久久WWW免费人成—看片| 亚洲一区欧洲一区| 麻豆亚洲av熟女国产一区二| 亚洲精品视频在线观看你懂的| 久久久高清免费视频| 99re6热视频精品免费观看| 亚洲一区二区免费视频| 成人最新午夜免费视频| 亚洲成人在线免费观看| 国产精品白浆在线观看免费| 最近中文字幕大全中文字幕免费| 国产精品无码免费播放| 在线观看的免费网站| 国产又粗又长又硬免费视频| 免费国产作爱视频网站| 国产免费资源高清小视频在线观看| 欧美在线看片A免费观看| 免费一级毛片在线播放| 国产AV无码专区亚洲AV男同| 亚洲国产精品一区二区久| 亚洲国产欧美一区二区三区|