Re: Try-except-finally paradox

2014-01-31 Thread Göktuğ Kayaalp
Terry Reedy tjre...@udel.edu writes:

I do not have any information on the topic, but I *imagine* that the
when RETURN_VALUE opcode is evaluated within the context of an except
block, it triggers a check for whether a corresponding finally block
exists and should it exist, it is triggered, much like a callback.
So, my *imaginary* algorithm works like this:

return:
  if within an except block EB:
if EB has a correspoinding final block FB
  run FB
else
  do return
  else
do return

In Jessica's example, as the finally block executes a RETURN_VALUE
opcode, and as this is *probably* a jump to the caller, the rest of the
code does not get a chance to be executed.

As I have said earlier, I by no means assert the truth of this idea I've
explained here, but it seems quite reasonable to me.

  gk

 On 1/30/2014 7:05 AM, Dave Angel wrote:
   Jessica Ross deathwea...@gmail.com Wrote in message:
 I found something like this in a StackOverflow discussion.
 def paradox():
 ... try:
 ... raise Exception(Exception raised during try)
 ... except:
 ... print Except after try
 ... return True
 ... finally:
 ... print Finally
 ... return False
 ... return None
 ...
 return_val = paradox()
 Except after try
 Finally
 return_val
 False

 I understand most of this.
 What I don't understand is why this returns False rather than True. Does 
 the finally short-circuit the return in the except block?


 The finally has to happen before any return inside the try or the
   except.  And once you're in the finally clause you'll finish it
   before resuming the except clause.  Since it has a return,  that
   will happen before the other returns. The one in the except block
   will never get reached.

 It's the only reasonable behavior., to my mind.

 Checking with the disassembled code, it appears that the except return
 happens first and is then caught and the value over-written

   2   0 SETUP_FINALLY   45 (to 48)
   3 SETUP_EXCEPT16 (to 22)

   3   6 LOAD_GLOBAL  0 (Exception)
   9 LOAD_CONST   1 ('Exception raised during try')
  12 CALL_FUNCTION1 (1 positional, 0 keyword pair)
  15 RAISE_VARARGS1
  18 POP_BLOCK
  19 JUMP_FORWARD22 (to 44)

   422 POP_TOP
  23 POP_TOP
  24 POP_TOP

   5  25 LOAD_GLOBAL  1 (print)
  28 LOAD_CONST   2 ('Except after try')
  31 CALL_FUNCTION1 (1 positional, 0 keyword pair)
  34 POP_TOP

   6  35 LOAD_CONST   3 (True)
  38 RETURN_VALUE
  39 POP_EXCEPT
  40 JUMP_FORWARD 1 (to 44)
  43 END_FINALLY
44 POP_BLOCK
  45 LOAD_CONST   0 (None)

   848 LOAD_GLOBAL  1 (print)
  51 LOAD_CONST   4 ('Finally')
  54 CALL_FUNCTION1 (1 positional, 0 keyword pair)
  57 POP_TOP

   9  58 LOAD_CONST   5 (False)
  61 RETURN_VALUE
  62 END_FINALLY

  10  63 LOAD_CONST   0 (None)
  66 RETURN_VALUE




 -- 
 Terry Jan Reedy

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Try-except-finally paradox

2014-01-30 Thread Chris Angelico
On Thu, Jan 30, 2014 at 11:05 PM, Dave Angel da...@davea.name wrote:
 The finally has to happen before any return inside the try or the
  except.  And once you're in the finally clause you'll finish it
  before resuming the except clause.  Since it has a return,  that
  will happen before the other returns. The one in the except block
  will never get reached.

 It's the only reasonable behavior., to my mind.

It's arguable that putting a return inside a finally is unreasonable
behaviour, but that's up to the programmer. A finally clause can be
used to do what might be done in C++ with a destructor: no matter how
this function/block exits, do this as you unwind the stack. In C++, I
might open a file like this:

void func()
{
ofstream output(output.txt);
// do a whole lot of stuff ...
// at the close brace, output.~output() will be called, which will
close the file
}

In Python, the equivalent would be:

def func():
try:
output = open(output.txt, w)
# do a whole lot of stuff ...
finally:
output.close()

(Actually, the Python equivalent would be to use a 'with' clause for
brevity, but 'with' uses try/finally under the covers, so it comes to
the same thing.) The concept of the finally clause is: Whether
execution runs off the end, hits a return statement, or throws an
exception, I need you do this before anything else happens. Having a
return statement inside 'finally' as well as in 'try' is a bit of a
corner case, since you're now saying Before you finish this function
and return something, I need you to return something else, which
doesn't usually make sense. If you think Python's behaviour is
confusing, first figure out what you would expect to happen in this
situation :)

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Try-except-finally paradox

2014-01-30 Thread MRAB

On 2014-01-30 13:02, Chris Angelico wrote:

On Thu, Jan 30, 2014 at 11:05 PM, Dave Angel da...@davea.name wrote:

The finally has to happen before any return inside the try or the
 except.  And once you're in the finally clause you'll finish it
 before resuming the except clause.  Since it has a return,  that
 will happen before the other returns. The one in the except block
 will never get reached.

It's the only reasonable behavior., to my mind.


It's arguable that putting a return inside a finally is unreasonable
behaviour, but that's up to the programmer. A finally clause can be
used to do what might be done in C++ with a destructor: no matter how
this function/block exits, do this as you unwind the stack. In C++, I
might open a file like this:

void func()
{
 ofstream output(output.txt);
 // do a whole lot of stuff ...
 // at the close brace, output.~output() will be called, which will
close the file
}

In Python, the equivalent would be:

def func():
 try:
 output = open(output.txt, w)
 # do a whole lot of stuff ...
 finally:
 output.close()

(Actually, the Python equivalent would be to use a 'with' clause for
brevity, but 'with' uses try/finally under the covers, so it comes to
the same thing.) The concept of the finally clause is: Whether
execution runs off the end, hits a return statement, or throws an
exception, I need you do this before anything else happens. Having a
return statement inside 'finally' as well as in 'try' is a bit of a
corner case, since you're now saying Before you finish this function
and return something, I need you to return something else, which
doesn't usually make sense. If you think Python's behaviour is
confusing, first figure out what you would expect to happen in this
situation :)


One of the reasons that the 'with' statement was added was to prevent
the mistake that you've just done. ;-)

What if the file can't be opened?

--
https://mail.python.org/mailman/listinfo/python-list


Re: Try-except-finally paradox

2014-01-30 Thread Chris Angelico
On Fri, Jan 31, 2014 at 12:11 AM, MRAB pyt...@mrabarnett.plus.com wrote:
 One of the reasons that the 'with' statement was added was to prevent
 the mistake that you've just done. ;-)

 What if the file can't be opened?

Yeah, whoops. The open shouldn't be inside try/finally.

def func():
output = open(output.txt, w)
try:
 # do a whole lot of stuff ...
finally:
 output.close()

But my point still stands, I believe :)

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Try-except-finally paradox

2014-01-30 Thread Rotwang

On 30/01/2014 06:33, Andrew Berg wrote:

On 2014.01.29 23:56, Jessica Ross wrote:

I found something like this in a StackOverflow discussion.

def paradox():

... try:
... raise Exception(Exception raised during try)
... except:
... print Except after try
... return True
... finally:
... print Finally
... return False
... return None
...

return_val = paradox()

Except after try
Finally

return_val

False

I understand most of this.
What I don't understand is why this returns False rather than True.
Does the finally short-circuit the return in the except block?


My guess would be that the interpreter doesn't let the finally block
get skipped under any circumstances, so the return value gets set to
True, but then it forces the finally block to be run before returning,
which changes the return value to False.


Mine too. We can check that the interpreter gets as far as evaluating 
the return value in the except block:


 def paradox2():
try:
raise Exception(Raise)
except:
print(Except)
return [print(Return), True][1]
finally:
print(Finally)
return False
return None

 ret = paradox2()
Except
Return
Finally
 ret
False
--
https://mail.python.org/mailman/listinfo/python-list


Re: Try-except-finally paradox

2014-01-30 Thread Ethan Furman

On 01/30/2014 10:12 AM, Rotwang wrote:

On 30/01/2014 06:33, Andrew Berg wrote:

On 2014.01.29 23:56, Jessica Ross wrote:


I found something like this in a StackOverflow discussion.
-- def paradox():
... try:
... raise Exception(Exception raised during try)
... except:
... print Except after try
... return True
... finally:
... print Finally
... return False
... return None
...
-- return_val = paradox()
Except after try
Finally
-- return_val
False

I understand most of this.
What I don't understand is why this returns False rather than True.
Does the finally short-circuit the return in the except block?


My guess would be that the interpreter doesn't let the finally block
get skipped under any circumstances, so the return value gets set to
True, but then it forces the finally block to be run before returning,
which changes the return value to False.


Mine too. We can check that the interpreter gets as far as evaluating the 
return value in the except block:

-- def paradox2():
   try:
   raise Exception(Raise)
   except:
   print(Except)
   return [print(Return), True][1]
   finally:
   print(Finally)
   return False
   return None

-- ret = paradox2()
Except
Return
Finally
-- ret
False


And just to be thorough, if the finally block doesn't have a return:

-- def paradox3():
try:
raise Exception(Raise)
except:
print(Except)
return [print(Return), True][1]
finally:
print(Finally)
return None

-- print(paradox3())
Except
Return
Finally
True

--
~Ethan~
--
https://mail.python.org/mailman/listinfo/python-list


Re: Try-except-finally paradox

2014-01-30 Thread Terry Reedy

On 1/30/2014 7:05 AM, Dave Angel wrote:

  Jessica Ross deathwea...@gmail.com Wrote in message:

I found something like this in a StackOverflow discussion.

def paradox():

... try:
... raise Exception(Exception raised during try)
... except:
... print Except after try
... return True
... finally:
... print Finally
... return False
... return None
...

return_val = paradox()

Except after try
Finally

return_val

False

I understand most of this.
What I don't understand is why this returns False rather than True. Does the 
finally short-circuit the return in the except block?



The finally has to happen before any return inside the try or the
  except.  And once you're in the finally clause you'll finish it
  before resuming the except clause.  Since it has a return,  that
  will happen before the other returns. The one in the except block
  will never get reached.

It's the only reasonable behavior., to my mind.


Checking with the disassembled code, it appears that the except return 
happens first and is then caught and the value over-written


  2   0 SETUP_FINALLY   45 (to 48)
  3 SETUP_EXCEPT16 (to 22)

  3   6 LOAD_GLOBAL  0 (Exception)
  9 LOAD_CONST   1 ('Exception raised during try')
 12 CALL_FUNCTION1 (1 positional, 0 keyword pair)
 15 RAISE_VARARGS1
 18 POP_BLOCK
 19 JUMP_FORWARD22 (to 44)

  422 POP_TOP
 23 POP_TOP
 24 POP_TOP

  5  25 LOAD_GLOBAL  1 (print)
 28 LOAD_CONST   2 ('Except after try')
 31 CALL_FUNCTION1 (1 positional, 0 keyword pair)
 34 POP_TOP

  6  35 LOAD_CONST   3 (True)
 38 RETURN_VALUE
 39 POP_EXCEPT
 40 JUMP_FORWARD 1 (to 44)
 43 END_FINALLY
   44 POP_BLOCK
 45 LOAD_CONST   0 (None)

  848 LOAD_GLOBAL  1 (print)
 51 LOAD_CONST   4 ('Finally')
 54 CALL_FUNCTION1 (1 positional, 0 keyword pair)
 57 POP_TOP

  9  58 LOAD_CONST   5 (False)
 61 RETURN_VALUE
 62 END_FINALLY

 10  63 LOAD_CONST   0 (None)
 66 RETURN_VALUE




--
Terry Jan Reedy

--
https://mail.python.org/mailman/listinfo/python-list


Try-except-finally paradox

2014-01-29 Thread Jessica Ross
I found something like this in a StackOverflow discussion.
 def paradox():
... try:
... raise Exception(Exception raised during try)
... except:
... print Except after try
... return True
... finally:
... print Finally
... return False
... return None
... 
 return_val = paradox()
Except after try
Finally
 return_val
False

I understand most of this.
What I don't understand is why this returns False rather than True. Does the 
finally short-circuit the return in the except block?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Try-except-finally paradox

2014-01-29 Thread Ian Kelly
On Jan 29, 2014 11:01 PM, Jessica Ross deathwea...@gmail.com wrote:

 I found something like this in a StackOverflow discussion.
  def paradox():
 ... try:
 ... raise Exception(Exception raised during try)
 ... except:
 ... print Except after try
 ... return True
 ... finally:
 ... print Finally
 ... return False
 ... return None
 ...
  return_val = paradox()
 Except after try
 Finally
  return_val
 False

 I understand most of this.
 What I don't understand is why this returns False rather than True. Does
the finally short-circuit the return in the except block?

The docs don't seem to specify what happens in this case, but this behavior
is intuitive to me. If the except suite had raised an exception instead of
returning, the return in the finally would suppress that. The generalized
rule appears to be that the control flow specification executed later
overrides the earlier.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Try-except-finally paradox

2014-01-29 Thread Andrew Berg
On 2014.01.29 23:56, Jessica Ross wrote:
 I found something like this in a StackOverflow discussion.
 def paradox():
 ... try:
 ... raise Exception(Exception raised during try)
 ... except:
 ... print Except after try
 ... return True
 ... finally:
 ... print Finally
 ... return False
 ... return None
 ... 
 return_val = paradox()
 Except after try
 Finally
 return_val
 False
 
 I understand most of this.
 What I don't understand is why this returns False rather than True. Does the 
 finally short-circuit the return in the except block?
 
My guess would be that the interpreter doesn't let the finally block get 
skipped under any circumstances, so the return value gets set to
True, but then it forces the finally block to be run before returning, which 
changes the return value to False.

-- 
CPython 3.3.2 | Windows NT 6.2.9200 / FreeBSD 10.0
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Try-except-finally paradox

2014-01-29 Thread wxjmfauth
Le jeudi 30 janvier 2014 06:56:16 UTC+1, Jessica Ross a écrit :
 I found something like this in a StackOverflow discussion.
 
  def paradox():
 
 ... try:
 
 ... raise Exception(Exception raised during try)
 
 ... except:
 
 ... print Except after try
 
 ... return True
 
 ... finally:
 
 ... print Finally
 
 ... return False
 
 ... return None
 
 ... 
 
  return_val = paradox()
 
 Except after try
 
 Finally
 
  return_val
 
 False
 
 
 
 I understand most of this.
 
 What I don't understand is why this returns False rather than True. Does the 
 finally short-circuit the return in the except block?



The paradox is, in my mind, that the fct paradox() is
programmed to be paradoxal.

Compare with:

 def noparadox(i):
... try:
... a = 1 / i
... print('Process')
... except ZeroDivisionError:
... print(ZeroDivisionError)
... a = '?'
... except Exception:
... print(Exception)
... a = '?'
... finally:
... print(Finally)
... return a
... 
 noparadox(2)
Process
Finally
0.5
 noparadox(0)
ZeroDivisionError
Finally
'?'
 noparadox('asdf')
Exception
Finally
'?'


jmf
-- 
https://mail.python.org/mailman/listinfo/python-list