Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > How to pop the interpreter's stack?

Reply
Thread Tools

How to pop the interpreter's stack?

 
 
Ethan Furman
Guest
Posts: n/a
 
      12-26-2010
Steven D'Aprano wrote:
> Right. But I have thought of a clever trick to get the result KJ was
> asking for, with the minimum of boilerplate code. Instead of this:
>
>
> def _pre_spam(args):
> if condition(args):
> raise SomeException("message")
> if another_condition(args):
> raise AnotherException("message")
> if third_condition(args):
> raise ThirdException("message")
>
> def spam(args):
> _pre_spam(args)
> do_useful_work()
>
>
> you can return the exceptions instead of raising them (exceptions are
> just objects, like everything else!), and then add one small piece of
> boilerplate to the spam() function:
>
>
> def _pre_spam(args):
> if condition(args):
> return SomeException("message")
> if another_condition(args):
> return AnotherException("message")
> if third_condition(args):
> return ThirdException("message")
>
> def spam(args):
> exc = _pre_spam(args)
> if exc: raise exc
> do_useful_work()


-1

You failed to mention that cleverness is not a prime requisite of the
python programmer -- in fact, it's usually frowned upon. The big
problem with the above code is you are back to passing errors in-band,
pretty much completely defeating the point of have an out-of-band channel.

~Ethan~
 
Reply With Quote
 
 
 
 
kj
Guest
Posts: n/a
 
      12-26-2010
In <mailman.280.1293287106.6505.python-list@python Robert Kern <(E-Mail Removed)> writes:

>Except that the *caller* never gets the traceback (unless if it deliberately
>inspects the stack for some metaprogramming reason). It gets the exception, and
>that is the same no matter what you do. The developer/user gets the traceback,
>and those implementation details *are* often important to them.



Just look at what Python shows you if you pass the wrong number of
arguments to a function:

>>> def spam(x, y, z): pass

....
>>> spam(1, 2)

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: spam() takes exactly 3 arguments (2 given)


That's it. The traceback stops at the point of the error. Python
doesn't show you all the underlying C-coded machinery that went
into detecting the error and emitting the error message. *No one*
needs this information at this point. All I'm saying is that I
want to do the same thing with my argument validation code as Python
does with its argument validation code: keep it out of sight. When
my argument validation code fires an exception ***there's no bug
in **my** code***. It's doing exactly what it's supposed to do.
Therefore, there's no need for me to debug anything, and certainly
no need for me to inspect the traceback all the way to the exception.
The bug is in the code that called my function with the wrong
arguments. The developer of that code has no more use for seeing
the traceback all the way to where my code raises the exception
than I have for seeing the traceback of Python's underlying C code
when I get an error like the one shown above.

~kj
 
Reply With Quote
 
 
 
 
kj
Guest
Posts: n/a
 
      12-26-2010
In <(E-Mail Removed)> Ethan Furman <(E-Mail Removed)> writes:

>You failed to mention that cleverness is not a prime requisite of the
>python programmer -- in fact, it's usually frowned upon.


That's the party line, anyway. I no longer believe it. I've been
crashing against one bit of cleverness after another in Python's
unification of types and classes...
 
Reply With Quote
 
John Nagle
Guest
Posts: n/a
 
      12-26-2010
On 12/25/2010 2:50 PM, Steven D'Aprano wrote:
> On Fri, 24 Dec 2010 10:51:32 -0800, John Nagle wrote:
>
>> On 12/24/2010 3:24 AM, Carl Banks wrote:
>>> On Dec 24, 1:24 am, Steven D'Aprano<steve
>>> (E-Mail Removed)> wrote:

>> All I'm
>>>> suggesting is that there should be a way of reducing the boilerplate
>>>> needed for this idiom:
>>>>
>>>> def _validate_arg(x):
>>>> if x == 'bad input': return False
>>>> return True
>>>>
>>>> def f(arg):
>>>> if not _validate_arg(arg):
>>>> raise ValueError
>>>> process(arg)
>>>>
>>>> to something more natural that doesn't needlessly expose
>>>> implementation details that are completely irrelevant to the caller.

>>
>> How about
>>
>> raise ValueError("Bad input %s to validate_arg" % (repr(arg),))
>>
>> You can pass arguments to most exceptions, and the content of the
>> exception is determined entirely by the code raising it.

>
> I know that exceptions can take arguments (usually string error
> messages). I was writing in short-hand. My apologies, I thought that
> would have been obvious
>
> Perhaps you have missed the context of the discussion. The context is
> that the called function delegates the job of validating input to a
> private function, which should be hidden from the caller (it's private,
> not part of the public API, subject to change, hidden, etc.) but
> tracebacks expose that information, obscuring the cause of the fault.
> (The fault being bad input to the public function, not an accidental bug
> in the private function.)
>
>
>> If end users are seeing uncaught tracebacks, the program is broken.

>
> Well, perhaps, but that's a separate issue. We're talking about the
> caller of the function seeing internal details, not the end use.


No, that is the issue, unless the program itself is examining the
stack traceback data. Python exception-catching has no notion of
what code raised the exception. Only the contents of the exception
object are normally available. So the "private function" is always
"hidden", unless you're debugging, in which case it shouldn't be
hidden.

Traceback is purely a debugging feature. In some Python
implementations, such as Shed Skin, you don't get tracebacks unless
you're running under a debugger.

John Nagle
 
Reply With Quote
 
Steve Holden
Guest
Posts: n/a
 
      12-27-2010
On 12/26/2010 2:14 PM, kj wrote:
> In <(E-Mail Removed)> Ethan Furman <(E-Mail Removed)> writes:
>
>> You failed to mention that cleverness is not a prime requisite of the
>> python programmer -- in fact, it's usually frowned upon.

>
> That's the party line, anyway. I no longer believe it. I've been
> crashing against one bit of cleverness after another in Python's
> unification of types and classes...


Well if you can find a way to implement a class system that doesn't use
clever tricks *in its implementation* please let me know.

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
PyCon 2011 Atlanta March 9-17 http://us.pycon.org/
See Python Video! http://python.mirocommunity.org/
Holden Web LLC http://www.holdenweb.com/
 
Reply With Quote
 
Steve Holden
Guest
Posts: n/a
 
      12-27-2010
On 12/26/2010 2:14 PM, kj wrote:
> In <(E-Mail Removed)> Ethan Furman <(E-Mail Removed)> writes:
>
>> You failed to mention that cleverness is not a prime requisite of the
>> python programmer -- in fact, it's usually frowned upon.

>
> That's the party line, anyway. I no longer believe it. I've been
> crashing against one bit of cleverness after another in Python's
> unification of types and classes...


Well if you can find a way to implement a class system that doesn't use
clever tricks *in its implementation* please let me know.

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
PyCon 2011 Atlanta March 9-17 http://us.pycon.org/
See Python Video! http://python.mirocommunity.org/
Holden Web LLC http://www.holdenweb.com/

 
Reply With Quote
 
misnomer@gmail.com
Guest
Posts: n/a
 
      12-27-2010
On Dec 23, 3:22*am, Steven D'Aprano <steve
(E-Mail Removed)> wrote:
> You seem to have completely missed that there will be no bug report,
> because this isn't a bug. (Or if it is a bug, the bug is elsewhere,
> external to the function that raises the exception.) It is part of the
> promised API. The fact that the exception is generated deep down some
> chain of function calls is irrelevant.


While the idea of being able to do this (create a general validation
exception) sounds mildly appealing at first, what happens when the
module implementing this documented API and documented error, has a
bug? It seems that the user, or even module developer in the midst of
writing, would now have no tools to easily tackle the problem, and no
useful information to submit in the required bug report.
 
Reply With Quote
 
Carl Banks
Guest
Posts: n/a
 
      12-27-2010
On Dec 26, 11:09*am, kj <(E-Mail Removed)> wrote:
> In <mailman.280.1293287106.6505.python-list@python Robert Kern <(E-Mail Removed)> writes:
>
> >Except that the *caller* never gets the traceback (unless if it deliberately
> >inspects the stack for some metaprogramming reason). It gets the exception, and
> >that is the same no matter what you do. The developer/user gets the traceback,
> >and those implementation details *are* often important to them.

>
> Just look at what Python shows you if you pass the wrong number of
> arguments to a function:
>
> >>> def spam(x, y, z): pass

> ...
> >>> spam(1, 2)

>
> Traceback (most recent call last):
> * File "<stdin>", line 1, in <module>
> TypeError: spam() takes exactly 3 arguments (2 given)
>
> That's it. *The traceback stops at the point of the error. *Python
> doesn't show you all the underlying C-coded machinery that went
> into detecting the error and emitting the error message. **No one*
> needs this information at this point. *All I'm saying is that I
> want to do the same thing with my argument validation code as Python
> does with its argument validation code: keep it out of sight. *When
> my argument validation code fires an exception ***there's no bug
> in **my** code***. *It's doing exactly what it's supposed to do.
> Therefore, there's no need for me to debug anything, and certainly
> no need for me to inspect the traceback all the way to the exception.
> The bug is in the code that called my function with the wrong
> arguments. *The developer of that code has no more use for seeing
> the traceback all the way to where my code raises the exception
> than I have for seeing the traceback of Python's underlying C code
> when I get an error like the one shown above.


Python makes no attempt to hide its machinery in tracebacks (that I'm
aware of); in fact stack points from internal Python functions,
classes, and modules appear in tracebacks all the time. The reason
you don't see traceback lines for Python's argument validation is it's
written in C. If it bothers you that much, you're welcome to write
you own argument validation in C, too.


Carl Banks
 
Reply With Quote
 
Carl Banks
Guest
Posts: n/a
 
      12-27-2010
On Dec 25, 2:49*pm, Steven D'Aprano <steve
(E-Mail Removed)> wrote:
> On Sat, 25 Dec 2010 09:17:27 -0500, Robert Kern wrote:
> > On 12/24/10 5:14 PM, Ethan Furman wrote:

>
> >> There are also times when I change the exception being raised to match
> >> what python expects from that type of object -- for example, from
> >> WhatEverException to KeyError for a dict-like object. So in this regard
> >> I agree with Steven.

>
> > Steven isn't arguing that particular point here, nor is anyone arguing
> > against it.

>
> Emphasis on *here*.
>
> You will note that in Python 3, if you raise an exception inside an
> except block, both the *original* and the new exception are printed. This
> is great for fixing bugs inside except blocks, but terribly disruptive
> for catching one error and raising another error in it's place, e.g.:
>
> try:
> * * x+0
> except ValueError, TypeError as e:
> * * # x is not a numeric value, e.g. a string or a NAN.
> * * raise MyError('x is not a number')
>
> The explicit raise is assumed to indicate a bug in the except block, and
> the original exception is printed as well.
>
> But that's a separate issue from what is being discussed here. What we're
> discussing here is the idea that a function should be able to delegate
> work to private subroutines without the caller being aware of that fact.
> When you return a value, the caller doesn't see the internal details of
> how you calculated the value, but if you deliberately raise an exception,
> the caller does. Often this is the right thing to do, but sometimes it
> isn't. E.g. you can't delegate input validation to a subroutine and raise
> inside the subroutine without obfuscating the traceback.



>>> import re
>>> re.compile(r"(")

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.6/re.py", line 190, in compile
return _compile(pattern, flags)
File "/usr/lib/python2.6/re.py", line 245, in _compile
raise error, v # invalid expression
sre_constants.error: unbalanced parenthesis


OHMYGOD HOW DARE the standard library allow the traceback list an
internal function that does input valididation!


Carl Banks
 
Reply With Quote
 
Steven D'Aprano
Guest
Posts: n/a
 
      12-27-2010
On Sun, 26 Dec 2010 09:15:32 -0800, Ethan Furman wrote:

> Steven D'Aprano wrote:
>> Right. But I have thought of a clever trick to get the result KJ was
>> asking for, with the minimum of boilerplate code. Instead of this:
>>
>>
>> def _pre_spam(args):
>> if condition(args):
>> raise SomeException("message")
>> if another_condition(args):
>> raise AnotherException("message")
>> if third_condition(args):
>> raise ThirdException("message")
>>
>> def spam(args):
>> _pre_spam(args)
>> do_useful_work()
>>
>>
>> you can return the exceptions instead of raising them (exceptions are
>> just objects, like everything else!), and then add one small piece of
>> boilerplate to the spam() function:
>>
>>
>> def _pre_spam(args):
>> if condition(args):
>> return SomeException("message")
>> if another_condition(args):
>> return AnotherException("message")
>> if third_condition(args):
>> return ThirdException("message")
>>
>> def spam(args):
>> exc = _pre_spam(args)
>> if exc: raise exc
>> do_useful_work()

>
> -1
>
> You failed to mention that cleverness is not a prime requisite of the
> python programmer -- in fact, it's usually frowned upon. The big
> problem with the above code is you are back to passing errors in-band,
> pretty much completely defeating the point of have an out-of-band
> channel.


How is that any worse than making _pre_spam() a validation function that
returns a bool?

def spam(args):
flag = _pre_spam(args)
if flag: raise SomeException()
do_useful_work()


Is that also frowned upon for being too clever?



--
Steven
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: How include a large array? Edward A. Falk C Programming 1 04-04-2013 08:07 PM
How to do server-side processing and then display pop-up with pop-up blocker enabled domtam@hotmail.com ASP .Net 2 02-04-2006 06:03 PM
pop up prevention problem; for wanted pop ups joe doe Firefox 2 03-03-2005 08:08 AM
Pop-up to Buy Pop-up software William Young Computer Support 4 01-24-2004 12:28 AM
Pop-Up Menager (pop-up blocker), to update it library? Ulisse Computer Information 1 10-27-2003 08:31 PM



Advertisments