1Class::Throwable(3) User Contributed Perl Documentation Class::Throwable(3)
2
3
4
6 Class::Throwable - A minimal lightweight exception class
7
9 use Class::Throwable;
10
11 # simple usage
12 eval {
13 # code code code,
14 if ($something_goes_wrong) {
15 throw Class::Throwable "Something has gone wrong";
16 }
17 };
18 if ($@) {
19 # we just print out the exception message here
20 print "There has been an exception: " $@->getMessage();
21 # but if we are debugging we get the whole
22 # stack trace as well
23 if (DEBUG) {
24 print $@->getStackTraceAsString();
25 }
26 }
27
28 # it can be used to catch perl exceptions
29 # and wrap them in a Class::Throwable exception
30 eval {
31 # generate a perl exception
32 eval "2 / 0";
33 # then throw our own with the
34 # perl exception as a sub-exception
35 throw Class::Throwable "Throwing an exception" => $@ if $@;
36 };
37 if ($@) {
38 # setting the verbosity to
39 # 2 gives a full stack trace
40 # including any sub-exceptions
41 # (see below for examples of
42 # this output format)
43 $@->toString(2);
44 }
45
46 # you can also declare inline exceptions
47 use Class::Throwable qw(My::App::Exception::IllegalOperation);
48
49 # set their global verbosity as well
50 # with the class method
51 My::App::Exception::IllegalOperation->setVerbosity(2);
52
53 eval {
54 throw My::App::Exception::IllegalOperation "Bad, real bad";
55 };
56
57 # can also declare subclasses of Class::Throwable
58 # in other files, then when you import them, you
59 # can set their verbosity
60 use My::Sub::Class::In::A::Separate::File (VERBOSE => 1);
61
62 throw My::Sub::Class::In::A::Separate::File "This exception will use a verbosity of 1";
63
64 # you can even create exceptions, then throw them later
65 my $e = Class::Throwable->new("Things have gone bad, but I need to do something first", $@);
66
67 # do something else ...
68
69 # then throw the exception we created earlier
70 throw $e
71
73 This module implements a minimal lightweight exception object. It is
74 meant to be a compromise between more basic solutions like Carp which
75 can only print information and cannot handle exception objects, and
76 more more complex solutions like Exception::Class which can be used to
77 define complex inline exceptions and has a number of module
78 dependencies.
79
80 Inline Exceptions
81 You can easily create new exception classes inline by passing them with
82 the "use" statment like this:
83
84 use Class::Throwable ('My::InlineException', 'My::Other::InlineException');
85
86 This is a quick and easy way to define arbitrary exception classes
87 without the need to manually create separate files or packages for
88 them. However, it should be noted that subclasses of Class::Throwable
89 cannot be used to define inline exceptions. If you attempt to do this,
90 an exception will be thrown.
91
92 Exception Verbosity
93 Class::Throwable offers a number of different types of diagnostic
94 outputs to suit your needs. Most of this is controlled through the
95 verbosity levels. If the verbosity level is set to 0 or below, an empty
96 string is returned. If the value is set to 1, then the exception's
97 message is returned. If the value is set to 2 or above, a full stack
98 trace along with full stack traces for all sub-exceptions are returned
99 in the format shown in "stackTraceToString". The default verbosity
100 setting is 1.
101
102 There are a number of ways in which you can set the verbosity of the
103 exceptions produced by Class::Throwable. The simplest way is as the
104 argument to the "toString" method. Using this method will override any
105 other settings you may have, and insure that the output of this method
106 is as you ask it to be.
107
108 $@->toString(2);
109
110 However, to use this style properly, this requires that you test the
111 value of $@ to be sure it is a Class::Throwable object. In some cases,
112 this may not be an issue, while in others, it makes more sense to set
113 verbosity on a wider scale.
114
115 For instance, if you define inline exceptions, then the simplest way to
116 set a verbostity level for a particular inline exception is through the
117 class method "setVerbosity".
118
119 use Class::Throwable qw(My::InlineException);
120
121 My::InlineException->setVerbosity(2);
122
123 This means that unless the "toString" verbosity argument overrides it,
124 all My::InlineException exceptions will use a verbosity setting of 2.
125 This method means that you can easily "print" the value of $@ and then
126 any My::InlineException exceptions will be automatically stringified
127 with a verbosity level of 2. This can simplify exception catching by
128 reducing the need to inspect the value of $@.
129
130 If you defined your exceptions as subclasses of Class::Throwable and
131 stored them in separate files, then another means of setting the
132 verbosity level is to assign it in the "use" statement.
133
134 use My::SeparateFileSubClass::Exception (VERBOSE => 2);
135
136 This has the same effect as the "setVerbosity" class method, in fact,
137 there is nothing to stop you from using the "setVerbosity" class method
138 in this case if you like. This method can also be used on
139 Class::Throwable itself, however, this does not set the verbosity level
140 for all subclasses, only for Class::Throwable exceptions.
141
142 There is one last method which can be used. This method has the widest
143 scope of all the methods. The variable
144 $Class::Throwable::DEFAULT_VERBOSITY can be set. Setting this value
145 will take effect if, 1) there is no value passed to the "toString"
146 method and 2) no verbosity level has been set for the particular class,
147 either through "setVerbosity" or the "use" statement.
148
149 Module exception retro-fitting
150 It is possible to retrofit a module to use Class::Throwable exceptions
151 if you want to. Basically this will allow modules which "die" with
152 either strings or some other value, to throw Class::Throwable based
153 exceptions. This feature is relatively new and should be considered to
154 be experimental, any feedback on it is greatly appreciated.
155
156 NOTE: It is important to do module retrofitting at the earliest
157 possible moment (preferrably before the module you are retrofitting is
158 compiled), as it will override "die" within a specified package.
159
160 Other than all this, retrofitting is quite simple. Here is a basic
161 example:
162
163 use Class::Throwable retrofit => 'My::Class';
164
165 Now anytime "die" is called within My::Class the calls will get
166 converted to a Class::Throwable instance. You can also control how
167 exceptions are converted like so:
168
169 use Class::Throwable retrofit => 'My::Class' => sub { My::Exception->throw(@_) };
170
171 Now anytime "die" is called within My::Class the calls will get
172 converted to a My::Exception instance instead. Or a slightly more
173 complex examples like this:
174
175 use Class::Throwable retrofit => (
176 'My::Class' => sub {
177 My::IllegalOperation->throw(@_) if $_[0] =~ /^Illegal Operation/;
178 My::Exception->throw(@_);
179 });
180
181 Now anytime "die" is called within My::Class the calls will get
182 converted to a My::Exception instance unless the exception matches the
183 reg-exp, in which case an My::IllegalOperation exception is thrown.
184
185 There are a couple of points to be made regarding this functionality.
186 First, it will add another stack frame to your exceptions (the retrofit
187 routine basically). This is probably avoidable, but as this is still
188 experimental I wanted to keep things somewhat simple. And second, if
189 you supply a custom "die" handler, you should be sure that it will
190 "die" somewhere within that routine. If you do not, you may have many
191 un-intended consequences.
192
194 Constructor
195 throw ($message, $sub_exception)
196 The most common way to construct an exception object is to "throw"
197 it. This method will construct the exception object, collect all
198 the information from the call stack and then "die".
199
200 The optional $message argument can be used to pass custom
201 information along with the exception object. Commonly this will be
202 a string, but this module makes no attempt to enforce that it be
203 anything other than a scalar, so more complex references or objects
204 can be used. If no $message is passed in, a default one will be
205 constructed for you.
206
207 The second optional argument, $sub_exception, can be used to retain
208 information about an exception which has been caught but might not
209 be appropriate to be re-thrown and is better wrapped within a new
210 exception object. While this argument will commonly be another
211 Class::Throwable object, that fact is not enforced so you can pass
212 in normal string based perl exceptions as well.
213
214 If this method is called as an instance method on an exception
215 object pre-built with "new", only then is the stack trace
216 information populated and the exception is then passed to "die".
217
218 new ($message, $sub_exception)
219 This is an alternate means of creating an exception object, it is
220 much like "throw", except that it does not collect stack trace
221 information or "die". It stores the $message and $sub_exception
222 values, and then returns the exception instance, to be possibly
223 thrown later on.
224
225 Class Methods
226 setVerbosity ($verbosity)
227 This is a class method, if it is called with an instance, and
228 exception will be thrown. This class method can be used to set the
229 verbosity level for a particular class. See the section "Exception
230 Verbosity" above for more details.
231
232 Accessors
233 getMessage
234 This allows access to the message in the exception, to allow more
235 granular exception reporting.
236
237 getStackTrace
238 This returns the raw stack trace information as an array of arrays.
239 There are 10 values returned by "caller" ($package, $filename,
240 $line, $subroutine, $hasargs, $wantarray, $evaltext, $is_require,
241 $hints, $bitmask) we do not bother to capture the last two as they
242 are subject to change and meant for internal use, all others are
243 retained in the order returned by "caller".
244
245 hasSubException
246 The returns true (1) if this exception has a sub-exception, and
247 false (0) otherwise.
248
249 getSubException
250 This allows access to the stored sub-exception.
251
252 Output Methods
253 This object overloads the stringification operator, and will call the
254 "toString" method to perform that stringification.
255
256 toString ($verbosity)
257 This will print out the exception object's information at a
258 variable level of verbosity which is specified be the optional
259 argument $verbosity. See the section "Exception Verbosity" above
260 for more details.
261
262 stringValue
263 This will return the normal perl stringified value of the object
264 without going through the "toString" method.
265
266 stackTraceToString
267 This method is used to print the stack trace information, the stack
268 trace is presented in the following format:
269
270 |--[ main::foo called in my_script.pl line 12 ]
271 |--[ main::bar called in my_script.pl line 14 ]
272 |--[ main::baz called in my_script.pl line 16 ]
273
275 Given the following code:
276
277 {
278 package Foo;
279 sub foo { eval { Bar::bar() }; throw Class::Throwable "Foo!!", $@ }
280
281 package Bar;
282 sub bar { eval { Baz::baz() }; throw Class::Throwable "Bar!!", $@ }
283
284 package Baz;
285 sub baz { throw Class::Throwable "Baz!!" }
286 }
287
288 eval { Foo::foo() };
289 print $@->toString($verbosity) if $@;
290
291 If you were to print the exception with verbosity of 0, you would get
292 no output at all. This mode can be used to suppress exception output if
293 needed. If you were to print the exception with verbosity of 1, you
294 would get this output.
295
296 Class::Throwable : Foo!!
297
298 If you were to print the exception with verbosity of 2, you would get
299 this output.
300
301 Class::Throwable : Foo!!
302 |--[ Foo::foo called in test.pl line 26 ]
303 |--[ main::(eval) called in test.pl line 26 ]
304 + Class::Throwable : Bar!!
305 |--[ Bar::bar called in test.pl line 19 ]
306 |--[ Foo::(eval) called in test.pl line 19 ]
307 |--[ Foo::foo called in test.pl line 26 ]
308 |--[ main::(eval) called in test.pl line 26 ]
309 + Class::Throwable : Baz!!
310 |--[ Baz::baz called in test.pl line 21 ]
311 |--[ Bar::(eval) called in test.pl line 21 ]
312 |--[ Bar::bar called in test.pl line 19 ]
313 |--[ Foo::(eval) called in test.pl line 19 ]
314 |--[ Foo::foo called in test.pl line 26 ]
315 |--[ main::(eval) called in test.pl line 26 ]
316
318 None that I am aware of. Of course, if you find a bug, let me know, and
319 I will be sure to fix it. This is based on code which has been heavily
320 used in production sites for over 2 years now without incident.
321
323 I use Devel::Cover to test the code coverage of my tests, below is the
324 Devel::Cover report on this module test suite.
325
326 ---------------------------- ------ ------ ------ ------ ------ ------ ------
327 File stmt branch cond sub pod time total
328 ---------------------------- ------ ------ ------ ------ ------ ------ ------
329 Class/Throwable.pm 100.0 98.0 63.6 100.0 100.0 100.0 95.7
330 ---------------------------- ------ ------ ------ ------ ------ ------ ------
331 Total 100.0 98.0 63.6 100.0 100.0 100.0 95.7
332 ---------------------------- ------ ------ ------ ------ ------ ------ ------
333
335 There are a number of ways to do exceptions with perl, I was not really
336 satisifed with the way anyone else did them, so I created this module.
337 However, if you find this module unsatisfactory, you may want to check
338 these out.
339
340 Throwable
341 Throwable is a role for classes that are meant to be thrown as
342 exceptions to standard program flow.
343
344 Exception::Class
345 This in one of the more common exception classes out there. It does
346 an excellent job with it's default behavior, and allows a number of
347 complex options which can likely serve any needs you might have. My
348 reasoning for not using this module is that I felt these extra
349 options made things more complex than they needed to be, it also
350 introduced a number of dependencies. I am not saying this module is
351 bloated at all, but that for me it was far more than I have found I
352 needed. If you have heavy duty exception needs, this is your
353 module.
354
355 Error
356 This is the classic perl exception module, complete with a
357 try/catch mechanism. This module has a lot of bad karma associated
358 with it because of the obscure nested closure memory leak that
359 try/catch has. I never really liked the way its exception object
360 Error::Simple did things either.
361
362 Exception
363 This module I have never really experimented with, so take my
364 opinion with a large grain of salt. My problem with this module was
365 always that it seemed to want to do too much. It attempts to make
366 perl into a language with real exceptions, but messing with %SIG
367 handlers and other such things. This can be dangerous territory
368 sometimes, and for me, far more than my needs.
369
371 stevan little, <stevan@iinteractive.com>
372
374 Copyright 2004 by Infinity Interactive, Inc.
375
376 <http://www.iinteractive.com>
377
378 This library is free software; you can redistribute it and/or modify it
379 under the same terms as Perl itself.
380
381
382
383perl v5.36.0 2023-01-20 Class::Throwable(3)