try: finally: question

D

djw

Hi, Folks-

I have a question regarding the "proper" use of try: finally:... Consider
some code like this:

d = Device.open()
try:
d.someMethodThatCanRaiseError(...)
if SomeCondition:
raise Error # Error is subclass of Exception
d.someMethodThatCanRaiseError(...)
... lots of other methods on d that can raise Error


finally:
d.close()


When I run this code, and an Error is raised, I get traceback (which I don't
want) and the program terminates (which I don't want). However, putting in
each method that can raise Error into a try: except: block doesn't help,
because I need to re-raise Error to break out of the block and get the
finally: to be triggered:


d = Device.open()
try:
try:
d.someMethodThatCanRaiseError(...)
except Error:
# Do something here
raise Error
if SomeCondition:
raise Error # Error is subclass of Exception
try:
d.someMethodThatCanRaiseError(...)
except Error:
# Do something here
raise Error

... lots of other methods on d that can raise Error


finally:
d.close()


I almost feel like I need a goto statement! Am I missing something about
finally:, or is it really not altogther very useful in practice?

Thanks,

-Don
 
P

Peter Hansen

djw said:
I have a question regarding the "proper" use of try: finally:... Consider
some code like this:
[...]
When I run this code, and an Error is raised, I get traceback (which I don't
want) and the program terminates (which I don't want).

I'm sorry if I misinterpret what you want, but it sounds like you
need nothing more than an enclosing try/except.

d = Device.open()
try:
try:
d.someMethodThatCanRaiseError(...)
if SomeCondition:
raise Error # Error is subclass of Exception
d.someMethodThatCanRaiseError(...)
... lots of other methods on d that can raise Error
finally:
d.close()
except:
# whatever you want here


Is anything wrong with that?
 
D

Donn Cave

Peter Hansen said:
djw said:
I have a question regarding the "proper" use of try: finally:... Consider
some code like this:
[...]
When I run this code, and an Error is raised, I get traceback (which I don't
want) and the program terminates (which I don't want).

I'm sorry if I misinterpret what you want, but it sounds like you
need nothing more than an enclosing try/except.

d = Device.open()
try:
try:
d.someMethodThatCanRaiseError(...)
if SomeCondition:
raise Error # Error is subclass of Exception
d.someMethodThatCanRaiseError(...)
... lots of other methods on d that can raise Error
finally:
d.close()
except:
# whatever you want here


Is anything wrong with that?

Didn't seem to be what he wanted, though. The best I could
make out was that he wanted a handler that receives control
on the exception, but leaves the exception in force enough
to cause an unwind to the next handler. He has a specific
exception handler for each step in a procedure, but doesn't
want to explicitly decide, in the handler, where to go next.
Didn't really see what it had to do with "finally", except
that in his example it was the next handler.

Donn Cave, (e-mail address removed)
 
D

djw

Peter said:
djw said:
I have a question regarding the "proper" use of try: finally:... Consider
some code like this:
[...]
When I run this code, and an Error is raised, I get traceback (which I
don't want) and the program terminates (which I don't want).

I'm sorry if I misinterpret what you want, but it sounds like you
need nothing more than an enclosing try/except.

d = Device.open()
try:
try:
d.someMethodThatCanRaiseError(...)
if SomeCondition:
raise Error # Error is subclass of Exception
d.someMethodThatCanRaiseError(...)
... lots of other methods on d that can raise Error
finally:
d.close()
except:
# whatever you want here


Is anything wrong with that?

OK, yeah, I think you are correct. What wasn't apparent to me is that a
finally: doesn't stop the exception from continuing to propagate. I just
wish you could intermix except: and finally: within the same try: block.

Thanks,

Don
 
P

Peter Hansen

djw said:
OK, yeah, I think you are correct. What wasn't apparent to me is that a
finally: doesn't stop the exception from continuing to propagate. I just
wish you could intermix except: and finally: within the same try: block.

You used to be able to do that, according to a recent thread on the
subject. It was removed because it was ambiguous what would happen.
For example, if an exception were raised in a finally clause which
came just before the except clause, would the except clause catch it?
Since the finally is technically outside of the try block, some
people thought it shouldn't be caught by the following except.
Others did. Guido nuked it.

Anyway, it would be purely syntactic sugar for what we have now,
saving you a few keystrokes and one extra level of indentation.
No big deal.

-Peter
 
A

Antoon Pardon

Op 2004-07-06 said:
You used to be able to do that, according to a recent thread on the
subject. It was removed because it was ambiguous what would happen.
For example, if an exception were raised in a finally clause which
came just before the except clause, would the except clause catch it?
Since the finally is technically outside of the try block, some
people thought it shouldn't be caught by the following except.
Others did. Guido nuked it.

Anyway, it would be purely syntactic sugar for what we have now,
saving you a few keystrokes and one extra level of indentation.
No big deal.

I don't agree. It is not unusual to nest try blocks. If you then
need to two instead of one because you can't combine a finally
with an except clause, you almost double the level of indentations.

IMO it is almost as bad as would not having an elif and needing
an extra indentation level for each else .. if
 
P

Peter Hansen

Antoon said:
Op 2004-07-06, Peter Hansen schreef <[email protected]>:
[about using finally and except on the same try block]
I don't agree.

With what statement don't you agree? The part about "you used to
be able to do that... [but] it was ambiguous ... Guido nuked it."?

Because that's a fact. It's hard not to agree with it...

And if it's the part about "syntactic sugar", then you should
understand that the term refers to alternate syntax which is
seen as "cleaner" or "simpler" in some way, but which is not
otherwise different in any way that affects the parse tree or
resulting code. And unless you think combined finally/except
clauses should be treated differently in the generated bytecode
than nested try/finally/except, it's *still* a fact that it
would just be "syntactic sugar", and arguing against facts is
pretty hard to do...
It is not unusual to nest try blocks. If you then
need to two instead of one because you can't combine a finally
with an except clause, you almost double the level of indentations.

In fact, you would precisely double the level of indentations.
It seems that's the price we have to pay for being human, since
apparently our brains aren't all wired the same way and allowing
finally/except to be combined was likely to lead to subtle bugs.
IMO it is almost as bad as would not having an elif and needing
an extra indentation level for each else .. if

Almost, perhaps. But can you see any way for similar ambiguity
to arise in the case of if/elif/else blocks? I think everybody
understands how they work just fine. The whole point is that
not everybody understood how the try/finally/except thing worked
(or they didn't agree with how it _should_ work).

I understand that you are arguing that it would be nicer to
allow try/finally/except. I agree! Unfortunately, (a) it was
removed and is probably unlikely to be added back in, (b) it
was ambiguous, and the ambiguity has not been resolved, so
until you or someone else can come up with a better approach
(and write a PEP) it will stay the way it is. And that's just
another fact, so it's pointless to try to argue against it.

Hmm... Also, I think it really *is* unusual (as in, "not usual"
meaning not really common) to nest try blocks. At least, I
recall lone try/finally or try/except blocks being much much
more common in most code than a mix. Perhaps my memory is
poor on this. Perhaps someone will actually go and research
it and prove it one way or the other. If it really is
very common, it might be worth revisiting the subject...
If it's not very common, then this is once again just another
discussion about syntactic sugar for an uncommon use case,
and that kind of thing is so last year. And the year before.
And....

-Peter
 
D

djw

Peter Hansen wrote:

[snip]
Hmm... Also, I think it really *is* unusual (as in, "not usual"
meaning not really common) to nest try blocks. At least, I
recall lone try/finally or try/except blocks being much much
more common in most code than a mix. Perhaps my memory is
poor on this. Perhaps someone will actually go and research
it and prove it one way or the other. If it really is
very common, it might be worth revisiting the subject...
If it's not very common, then this is once again just another
discussion about syntactic sugar for an uncommon use case,
and that kind of thing is so last year. And the year before.
And....

-Peter

I am suprised that what I am trying to accomplish is unusual. Basically, I
want to acquire some resource/object (that requires cleanup). Then make
some calls against that object/resource, catching any excpetions along the
way (assuming that try/except is the right way to do this). If anything bad
happens, I want stop opererating on the object and insure that the object
is cleaned up (presumably a finally is the best way to do this).

This seems like a really normal bit of code to me. I am suprised there isn't
a more elegant way to handle this (I thought that try/except/finally would
come to the rescue, but...) Is there a better way to handle this situation?

-Don
 
P

Peter Hansen

djw said:
I am suprised that what I am trying to accomplish is unusual. Basically, I
want to acquire some resource/object (that requires cleanup).

It *is* unusual, in the way I mean, because relatively little code
is involved with resource cleanup when it's required (in Python,
anyway), and relatively little resource cleanup is required when
programming, in general.
This seems like a really normal bit of code to me.

Maybe I'm drawing too fine a line here. I'm using "usual" and
"unusual" in the sense of "frequently occurring or not", rather than
in the sense of "normal or really weird".

It's very normal. It's just not so frequently occurring that
the nested finally/except should be seen as a major roadblock.
Not that one example tells much about the general case, but: I
just wrote a little inventory-tracking application, very small.
It has one finally (for a database commit), and two excepts
(basically around things that could have been if/thens but
are slightly cleaner as exception handling code). None of
these cases required bringing in a nested try. I think that's
the "usual" pattern.

If you find yourself needing to write such things very often,
I think you're probably not writing your code in a very modular
way, as it would then be more reusable and therefore require
being written much less often...

-Peter
 
D

Donn Cave

djw <[email protected]> said:
Peter Hansen wrote:

[snip]
Hmm... Also, I think it really *is* unusual (as in, "not usual"
meaning not really common) to nest try blocks. At least, I
recall lone try/finally or try/except blocks being much much
more common in most code than a mix. Perhaps my memory is
poor on this. Perhaps someone will actually go and research
it and prove it one way or the other. If it really is
very common, it might be worth revisiting the subject...
If it's not very common, then this is once again just another
discussion about syntactic sugar for an uncommon use case,
and that kind of thing is so last year. And the year before.
And....

-Peter

I am suprised that what I am trying to accomplish is unusual. Basically, I
want to acquire some resource/object (that requires cleanup). Then make
some calls against that object/resource, catching any excpetions along the
way (assuming that try/except is the right way to do this). If anything bad
happens, I want stop opererating on the object and insure that the object
is cleaned up (presumably a finally is the best way to do this).

This seems like a really normal bit of code to me. I am suprised there isn't
a more elegant way to handle this (I thought that try/except/finally would
come to the rescue, but...) Is there a better way to handle this situation?

Not per se. My reflex would be to suggest more functions,
like

def f(p0, p1):
t = acquire_resource(p0)
try:
v = ft(p1)
finally:
release_resource(t)
return v

def ft(p1):
try:
x = g(p1)
except Eg, ev:
print >> sys.stderr, ev
return None
try:
return fx(x)
except:
gu(x)
raise

def fx(x):
try:
return fy(h(x))
except Eh, ev:
print >> sys.stderr, ev
raise

etc. Note that the exception handling will be more or
less elaborate depending on how much you can take for
granted about what exceptions may be raised, what state
you need to recover from them, etc.'

Conceptually, what you're after is a nested try: block,
like

try:
x = g(p1)
try:
y = h(x)
try:
...
except:
...
except:
handle h error
except:
handle g error

That's how you handle an exception from g without
proceeding to h, with try/except alone. I don't find
that grossly wrong, it's just more palatable with a
few functions when it gets very deep.

Donn Cave, (e-mail address removed)
 
D

djw

Peter said:
It *is* unusual, in the way I mean, because relatively little code
is involved with resource cleanup when it's required (in Python,
anyway), and relatively little resource cleanup is required when
programming, in general.

I would agree (with regards to straight Python), but I disagree when you
include I/O. The I/O I am interacting with requires cleanup. Simply
allowing the device object I created to go out of scope and be
automatically cleaned up does not cause the I/O to be cleaned up properly.
Maybe I'm drawing too fine a line here. I'm using "usual" and
"unusual" in the sense of "frequently occurring or not", rather than
in the sense of "normal or really weird".

It's very normal. It's just not so frequently occurring that
the nested finally/except should be seen as a major roadblock.
Not that one example tells much about the general case, but: I
just wrote a little inventory-tracking application, very small.
It has one finally (for a database commit), and two excepts
(basically around things that could have been if/thens but
are slightly cleaner as exception handling code). None of
these cases required bringing in a nested try. I think that's
the "usual" pattern.

If you find yourself needing to write such things very often,
I think you're probably not writing your code in a very modular
way, as it would then be more reusable and therefore require
being written much less often...

Point taken. Its not that I'm doing this that often, its just when I do it
seems awkward. Since I find most Python code to be rather elegant and
concise, awkward situations like this tend to stick out glaringly to me.

-Don
 
A

Antoon Pardon

Op 2004-07-07 said:
Antoon said:
Op 2004-07-06, Peter Hansen schreef <[email protected]>:
[about using finally and except on the same try block]
I don't agree.

With what statement don't you agree? The part about "you used to
be able to do that... [but] it was ambiguous ... Guido nuked it."?

That it is no big deal.
Because that's a fact. It's hard not to agree with it...

And if it's the part about "syntactic sugar", then you should
understand that the term refers to alternate syntax which is
seen as "cleaner" or "simpler" in some way, but which is not
otherwise different in any way that affects the parse tree or
resulting code. And unless you think combined finally/except
clauses should be treated differently in the generated bytecode
than nested try/finally/except, it's *still* a fact that it
would just be "syntactic sugar", and arguing against facts is
pretty hard to do...


In fact, you would precisely double the level of indentations.
It seems that's the price we have to pay for being human, since
apparently our brains aren't all wired the same way and allowing
finally/except to be combined was likely to lead to subtle bugs.

Oh come on, I though python was for consenting adults?

Personnaly I think that allowing += operators for unmutable
object will lead to subtle bugs too, because if you see
code like

b = a
a += c

You don't know whether a and b are still the same object or not.

This will IMO be more confusing then a combined finally, except
clause, because the latter can be clearly documented in how
it behaves, while the above depends on the type of the variables.
Almost, perhaps. But can you see any way for similar ambiguity
to arise in the case of if/elif/else blocks? I think everybody
understands how they work just fine. The whole point is that
not everybody understood how the try/finally/except thing worked
(or they didn't agree with how it _should_ work).

So what? When I complained about the ambiguity that was introduced
by the introduction of the += and like operators, people told me
that:

1) Error caused by not reading the docs carefull enough were
my own fault

2) That I could always write things in such a way that there
would be no ambiguity.

So these arguments seem to be just as valid with a combined
except: finaly: clause.
I understand that you are arguing that it would be nicer to
allow try/finally/except. I agree! Unfortunately, (a) it was
removed and is probably unlikely to be added back in, (b) it
was ambiguous, and the ambiguity has not been resolved, so
until you or someone else can come up with a better approach
(and write a PEP) it will stay the way it is. And that's just
another fact, so it's pointless to try to argue against it.

Well I think it really isn't that hard to define the behaviour
of

try:
except expr1:
finaly:
except expr2:

to be the same as

try:
try:
try:
except expr1:
finaly:
except expr2:

In fact if it wasn't for the indentations rules in python
I wouldn't care because without them I could simply write
something like

try: try: try:
except expr1:
finaly:
except expr2:

which is how I write my if ... else blocks in C.

However I'm not going to write a PEP. The impression that there
is some double standard going on is just too strong, where powerfull,
flexible and/or ambiguous concepts that are in the language are defended
with the argument that python is for consenting adults and
powerfull, flexible and/or ambiguous concepts that are not
in the language are opposed because they can lead to subtle
bugs.

Maybe the python community should make up its mind and decide
what it wants. A language for consenting adults or protection
against subtle bugs.
Hmm... Also, I think it really *is* unusual (as in, "not usual"
meaning not really common) to nest try blocks. At least, I
recall lone try/finally or try/except blocks being much much
more common in most code than a mix. Perhaps my memory is
poor on this. Perhaps someone will actually go and research
it and prove it one way or the other. If it really is
very common, it might be worth revisiting the subject...
If it's not very common, then this is once again just another
discussion about syntactic sugar for an uncommon use case,
and that kind of thing is so last year. And the year before.
And....

One can argue the opposite too. Why remove it, if the subtle
bugs can occur only in unusual cases. Let those who need it
and know what they are doing use it. That is what I understand
about a language for consenting adults.
 
P

Peter Hansen

Antoon said:
Op 2004-07-07, Peter Hansen schreef <[email protected]>:
Personnaly I think that allowing += operators for unmutable
object will lead to subtle bugs too, because if you see
code like

b = a
a += c

You don't know whether a and b are still the same object or not.

I agree with you on this one. I don't like the way += etc
works. Also don't use it except for integers...
Well I think it really isn't that hard to define the behaviour
of

try:
except expr1:
finaly:
except expr2:

to be the same as

try:
try:
try:
except expr1:
finaly:
except expr2:

Interesting, except that this is *not* how it was implemented
before. Why don't you write a PEP and see if you can get your
solution to the problem implemented? Presenting it as a reason
why the previous, *different* solution should have been kept
doesn't make sense.
However I'm not going to write a PEP.
Dang.

Maybe the python community should make up its mind and decide
what it wants. A language for consenting adults or protection
against subtle bugs.

It wants to avoid subtle bugs, but unfortunately it sometimes
makes mistakes in how it does that.
One can argue the opposite too. Why remove it, if the subtle
bugs can occur only in unusual cases. Let those who need it
and know what they are doing use it. That is what I understand
about a language for consenting adults.

You misunderstand (IMHO) what "consenting adults" is about.
I tried to make the point in a previous thread about subtle
problems with threads... some types of bugs are too subtle
to allow the consenting adults thing to hold sway. That's
just my opinion, though. I'm not sure it's really shared by
anyone else in the community.

Threads I happen to know very well, and know many (but perhaps
not all) of the risks involved. I also know very many good
programmers who don't really understand threading issues
fully, yet. Nobody knows how to test well for threading
problems, so advice like "always use a Queue" is best.

Exceptions are not generally things that are exercised by
normal application runs, or even by most unit tests (unless
you are doing test-driven development). Therefore subtle
problems with exceptions should be "disallowed" by appropriate
language changes.

Something like += should work exactly like people expect
it to. The fact that it sometimes doesn't means it is a
wart and we should reconsider it. That probably won't happen,
so we're stuck with it. (?)

The thing that "consenting adults" usually applies to is
either access control (private, public, etc), or types.
Improvements in the area of types are expected in the future,
so let's ignore that one. Access control: this is now
pretty well understood to be a "problem" that is more in
the programmer's brain than in reality. Not having it in
the BSDM (BDSM?) style of C++ or Java doesn't lead to
subtle bugs, and the huge number of working Python programs
which have *no* access specifiers (or whatever they're called)
proves the point.

I'd go on, but thankfully for those of you reading I've got
a meeting I can just barely make it to so I'll stop here. :)

-Peter
 
A

Antoon Pardon

Op 2004-07-08 said:
I agree with you on this one. I don't like the way += etc
works. Also don't use it except for integers...


Interesting, except that this is *not* how it was implemented
before. Why don't you write a PEP and see if you can get your
solution to the problem implemented? Presenting it as a reason
why the previous, *different* solution should have been kept
doesn't make sense.


Dang.

Well I might reconsider. But I have no experience with this
whatsoever and my impression is that it is a rather involved
undertaking. In any case I doubt that it will be accepted
for the following reason: The proposal suggest that

try:
except expr1:
except expr2:

would be the same as

try:
try:
except expr1:
except expr2

which isn't the case

So maybe defining behaviour that is consistent with current
behaviour wouldn't be so simple after all.

It wants to avoid subtle bugs, but unfortunately it sometimes
makes mistakes in how it does that.


You misunderstand (IMHO) what "consenting adults" is about.
I tried to make the point in a previous thread about subtle
problems with threads... some types of bugs are too subtle
to allow the consenting adults thing to hold sway. That's
just my opinion, though. I'm not sure it's really shared by
anyone else in the community.

The problem is, everybody has an other opinion about which
types of bugs are too subtle. People who want to put some
feature in the language that can limit the programmer
mostly do because they want to avoid bugs which they consider
too subtle, so how do we determine which bugs are realy
too subtle and which are not? My impresion here is that
most people just use themselves as yardstick here and
declares those bugs that are too subtle for them as
being too subtle in general. IMO if you don't like it
when others say a feature will introduce too subtle
bugs too allow, when you feel you will be able to
cope, you shouldn't use the same argument. If you are
not comfortable with something, just avoid it and
code in a different way instead of making it impossible
for others to use.
Threads I happen to know very well, and know many (but perhaps
not all) of the risks involved. I also know very many good
programmers who don't really understand threading issues
fully, yet. Nobody knows how to test well for threading
problems, so advice like "always use a Queue" is best.

Sure, but lets look at the problem of not allowing one
thread to pause, interrupt or raise an exception in
an other thread. The defense for not allowing these
things has been that they would introduce suble bugs.

However it is my feeling that not allowing them will
sometimes complicate the code unnecessary. Suppose
you have a very complicated algorithm that you want
to start in a seperate thread. Suppose that this is
in a gui program and you want to allow the user
to interrupt the process if he finds it is taking too
long. Since this is not just a while loop, you are
now obligated to springle the code with test that
check whether or not the user wants to interrupt.

If one thread could raise an exception in an other
one, this could be far easier.

I agree Queues are in general a good solution, but
sometimes they are not and cramming a situation
that doesn't fit a Queue in one anyway just increases
the mess.
Exceptions are not generally things that are exercised by
normal application runs, or even by most unit tests (unless
you are doing test-driven development). Therefore subtle
problems with exceptions should be "disallowed" by appropriate
language changes.

I don't agree with that logic.
Something like += should work exactly like people expect
it to. The fact that it sometimes doesn't means it is a
wart and we should reconsider it. That probably won't happen,
so we're stuck with it. (?)

Well I wouldn't mind if it wouldn't work exactly as I expected.
What I expect is not always correct. However I do think that
it is important that behaviour in a language is consistent.
If += would always have yielded a new object, that is something
I could have more easily lived with because after maybe a first
surprise the behaviour would be consistent and thus predictable.
The thing that "consenting adults" usually applies to is
either access control (private, public, etc), or types.
Improvements in the area of types are expected in the future,
so let's ignore that one. Access control: this is now
pretty well understood to be a "problem" that is more in
the programmer's brain than in reality. Not having it in
the BSDM (BDSM?) style of C++ or Java doesn't lead to
subtle bugs, and the huge number of working Python programs
which have *no* access specifiers (or whatever they're called)
proves the point.

But IMO it could go further. One program can signal an other.
That is an old practice that still is around. So why not
allow one thread to "signal" an other.
 
P

Peter Hansen

Antoon said:
Sure, but lets look at the problem of not allowing one
thread to pause, interrupt or raise an exception in
an other thread. The defense for not allowing these
things has been that they would introduce suble bugs.

Actually, I think it's only interrupting that's been
discussed, and the main issues are (a) what to do if
the thread is blocked in an external (extension) call,
and (b) if the answer to (a) is "nuke the thread anyway!"
then what to do about cleanup.

Pausing shouldn't be an issue, though I'm not sure I
know any decent usecase for it. Raising an exception
should be pretty straightforward, and I have sneaking
suspicion (actually, it's a memory, and probably a wrong
one!) that that's how it's done in the addition that was
made to the core recently via a call in an extension
(Google Groups would bring up a message from Alex Martelli
describing it, I believe, or was it Aahz?).
If one thread could raise an exception in an other
one, this could be far easier.

Anyone interested should try to dig up that past reference
to an addition that was made to allow killing threads.
I ought to remember whether it raised an exception, but
I don't. I agree that would probably be the best way
to handle it, but a lot of people who insist they need
thread killing will probably be disappointed if it can't
kill a thread that is caught in an external routine, or
if it can kill such threads, they will end up writing
code that is buggy because it doesn't clean things up
properly... oh well.
But IMO it could go further. One program can signal an other.
That is an old practice that still is around. So why not
allow one thread to "signal" an other.

Sounds easy to say, but what does it mean? What actually
happens in the thread that is signalled? How does it process
the signal if it's blocked, say in a socket.accept() call,
for two minutes?
 
A

Antoon Pardon

Op 2004-07-08 said:
Actually, I think it's only interrupting that's been
discussed,

Well the few times I saw the discussion coming up I
tried to expand it, but with little succes.
and the main issues are (a) what to do if
the thread is blocked in an external (extension) call,
and (b) if the answer to (a) is "nuke the thread anyway!"
then what to do about cleanup.

Well my first thought would be to send the thread a
signal. This way an extension call could install
a signal handler if it needed to cleanup things.
Pausing shouldn't be an issue, though I'm not sure I
know any decent usecase for it. Raising an exception
should be pretty straightforward, and I have sneaking
suspicion (actually, it's a memory, and probably a wrong
one!) that that's how it's done in the addition that was
made to the core recently via a call in an extension
(Google Groups would bring up a message from Alex Martelli
describing it, I believe, or was it Aahz?).

Yes I found something but it seems only available in
extension code.
Anyone interested should try to dig up that past reference
to an addition that was made to allow killing threads.
I ought to remember whether it raised an exception, but
I don't. I agree that would probably be the best way
to handle it, but a lot of people who insist they need
thread killing will probably be disappointed if it can't
kill a thread that is caught in an external routine, or
if it can kill such threads, they will end up writing
code that is buggy because it doesn't clean things up
properly... oh well.

People write buggy code all the time. Even in none threaded
code it might be necessary to cleanup things, and it isn't
done properly because people didn't anticipate a particular
exception being raised.

Sounds easy to say, but what does it mean? What actually
happens in the thread that is signalled?

The same that happens in a program that is signaled.
The signalhanler is called.
How does it process
the signal if it's blocked, say in a socket.accept() call,
for two minutes?

Well what happens in a program that gets signalled and
is blocked in a socket.accept() call for two minutes?

Well I went to look at the signal documentation and I must
say I'm a bit annoyed by how signals are handled in python.
As I understand it is impossible to interrupt a python
program by typing ^C, while it is running extension code.
The interruption will occur when the extension code is
done. I think this is a bad idea.
 
N

Nick Smallbone

djw said:
I would agree (with regards to straight Python), but I disagree when you
include I/O. The I/O I am interacting with requires cleanup. Simply
allowing the device object I created to go out of scope and be
automatically cleaned up does not cause the I/O to be cleaned up properly.

Why don't you define __del__() in the object so it can do its own cleanup?
Apologies if I've missed something important.

Nick
 
P

Peter Hansen

Nick said:
Why don't you define __del__() in the object so it can do its own cleanup?
Apologies if I've missed something important.

Yeah, all the past and recent threads talking about how you can't
really rely on __del__(). ;-)

-Peter
 
M

Mark 'Kamikaze' Hughes

Peter Hansen said:
I understand that you are arguing that it would be nicer to
allow try/finally/except. I agree! Unfortunately, (a) it was
removed and is probably unlikely to be added back in, (b) it
was ambiguous, and the ambiguity has not been resolved, so
until you or someone else can come up with a better approach
(and write a PEP) it will stay the way it is. And that's just
another fact, so it's pointless to try to argue against it.

In Java, try...catch...finally has a very clearly defined order: the
try block is performed, if there's an exception it goes to the first
matching catch, and then whether or not there was an exception, the
finally block is performed. Sometimes this leads to flags that have to
be tested in the finally block to decide what to do, but at least it's
consistent and avoids repeated cleanup code.

But Python is not Java, nor should it be, and there's no particular
problem with one additional nesting layer to indicate exactly what
sequence things are done in.
 
T

Tim Peters

[Peter Hansen]
[Mark 'Kamikaze' Hughes]
In Java, try...catch...finally has a very clearly defined order: the
try block is performed, if there's an exception it goes to the first
matching catch, and then whether or not there was an exception, the
finally block is performed.

Ancient Python also had a clearly defined order, but that doesn't
matter: the point was that, in practice, people couldn't remember the
details, and routinely wrote broken code as a result. There's nothing
especially compelling about either way of resolving the question (note
that an enthusiastic "but it's obvious that an exception raised during
an 'except' clause should not enter the 'finally' block!" was one old
response in this thread), and Python doesn't allow int+string for
exactly the same reason. Not because it can't be defined clearly, but
because any way of defining it is so arbitrary it leaves half of
programmers believing that the other way of defining it was "the only
obvious" way. Don't allow mixing except with finally, and the
programmer has to be explicit about their intent. That was (and
remains) a Pythonic solution.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,262
Messages
2,571,049
Members
48,769
Latest member
Clifft

Latest Threads

Top