Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #32035 > unrolled thread
| Started by | andrea crotti <andrea.crotti.0@gmail.com> |
|---|---|
| First post | 2012-10-24 13:51 +0100 |
| Last post | 2012-10-26 03:02 +1100 |
| Articles | 8 — 5 participants |
Back to article view | Back to comp.lang.python
resume execution after catching with an excepthook? andrea crotti <andrea.crotti.0@gmail.com> - 2012-10-24 13:51 +0100
Re: resume execution after catching with an excepthook? Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-10-25 01:15 +0000
Re: resume execution after catching with an excepthook? andrea crotti <andrea.crotti.0@gmail.com> - 2012-10-25 15:27 +0100
Re: resume execution after catching with an excepthook? Chris Angelico <rosuav@gmail.com> - 2012-10-26 01:51 +1100
Re: resume execution after catching with an excepthook? Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-10-25 15:40 +0000
RE: resume execution after catching with an excepthook? "Prasad, Ramit" <ramit.prasad@jpmorgan.com> - 2012-10-25 20:59 +0000
Re: resume execution after catching with an excepthook? Hans Mulder <hansmu@xs4all.nl> - 2012-10-25 17:31 +0200
Re: resume execution after catching with an excepthook? Chris Angelico <rosuav@gmail.com> - 2012-10-26 03:02 +1100
| From | andrea crotti <andrea.crotti.0@gmail.com> |
|---|---|
| Date | 2012-10-24 13:51 +0100 |
| Subject | resume execution after catching with an excepthook? |
| Message-ID | <mailman.2758.1351083094.27098.python-list@python.org> |
So I would like to be able to ask for confirmation when I receive a C-c,
and continue if the answer is "N/n".
I'm already using an exception handler set with sys.excepthook, but I
can't make it work with the confirm_exit, because it's going to quit in
any case..
A possible solution would be to do a global "try/except
KeyboardInterrupt", but since I already have an excepthook I wanted to
use this. Any way to make it continue where it was running after the
exception is handled?
def confirm_exit():
while True:
q = raw_input("This will quit the program, are you sure? [y/N]")
if q in ('y', 'Y'):
sys.exit(0)
elif q in ('n', 'N'):
print("Continuing execution")
# just go back to normal execution, is it possible??
break
def _exception_handler(etype, value, tb):
if etype == KeyboardInterrupt:
confirm_exit()
else:
sys.exit(1)
def set_exception_handler():
sys.excepthook = _exception_handler
[toc] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2012-10-25 01:15 +0000 |
| Message-ID | <5088929e$0$29978$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #32035 |
On Wed, 24 Oct 2012 13:51:30 +0100, andrea crotti wrote:
> So I would like to be able to ask for confirmation when I receive a C-c,
> and continue if the answer is "N/n".
I don't think there is any way to do this directly.
Without a try...except block, execution will cease after an exception is
caught, even when using sys.excepthook. I don't believe that there is any
way to jump back to the line of code that just failed (and why would you,
it will just fail again) or the next line (which will likely fail because
the previous line failed).
I think the only way you can do this is to write your own execution loop:
while True:
try:
run(next_command())
except KeyboardInterrupt:
if confirm_quit():
break
Of course you need to make run() atomic, or use transactions that can be
reverted or backed out of. How plausible this is depends on what you are
trying to do -- Python's Ctrl-C is not really designed to be ignored.
Perhaps a better approach would be to treat Ctrl-C as an unconditional
exit, and periodically poll the keyboard for another key press to use as
a conditional exit. Here's a snippet of platform-specific code to get a
key press:
http://code.activestate.com/recipes/577977
Note however that it blocks if there is no key press waiting.
I suspect that you may need a proper event loop, as provided by GUI
frameworks, or curses.
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | andrea crotti <andrea.crotti.0@gmail.com> |
|---|---|
| Date | 2012-10-25 15:27 +0100 |
| Message-ID | <mailman.2844.1351175253.27098.python-list@python.org> |
| In reply to | #32083 |
2012/10/25 Steven D'Aprano <steve+comp.lang.python@pearwood.info>: > On Wed, 24 Oct 2012 13:51:30 +0100, andrea crotti wrote: > >> So I would like to be able to ask for confirmation when I receive a C-c, >> and continue if the answer is "N/n". > > I don't think there is any way to do this directly. > > Without a try...except block, execution will cease after an exception is > caught, even when using sys.excepthook. I don't believe that there is any > way to jump back to the line of code that just failed (and why would you, > it will just fail again) or the next line (which will likely fail because > the previous line failed). > > I think the only way you can do this is to write your own execution loop: > > while True: > try: > run(next_command()) > except KeyboardInterrupt: > if confirm_quit(): > break > > > Of course you need to make run() atomic, or use transactions that can be > reverted or backed out of. How plausible this is depends on what you are > trying to do -- Python's Ctrl-C is not really designed to be ignored. > > Perhaps a better approach would be to treat Ctrl-C as an unconditional > exit, and periodically poll the keyboard for another key press to use as > a conditional exit. Here's a snippet of platform-specific code to get a > key press: > > http://code.activestate.com/recipes/577977 > > Note however that it blocks if there is no key press waiting. > > I suspect that you may need a proper event loop, as provided by GUI > frameworks, or curses. > > > > -- > Steven > -- > http://mail.python.org/mailman/listinfo/python-list Ok thanks, but here the point is not to resume something that is going to fail again, just to avoid accidental kill of processes that take a long time. Probably needed only by me in debugging mode, but anyway I can do the simple try/except then, thanks..
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2012-10-26 01:51 +1100 |
| Message-ID | <mailman.2845.1351176706.27098.python-list@python.org> |
| In reply to | #32083 |
On Thu, Oct 25, 2012 at 12:15 PM, Steven D'Aprano <steve+comp.lang.python@pearwood.info> wrote: > I don't believe that there is any > way to jump back to the line of code that just failed (and why would you, > it will just fail again) There are several reasons to retry something after an exception, mainly if some external state gets changed. Virtual memory is usually implemented using traps, so the OS handles an interrupt by paging something in from the disk, then retrying the "failing" instruction. The old-favorite "Abort, retry, ignore[, fail]?" prompt from DOS has the same notion; you tried to save a file onto a write-protected floppy disk, an exception is thrown, you handle the exception by getting the user to unprotect or change disks, and you resume where you left off. CPU-level interrupts always have a return address for that exact reason. Handling Ctrl-C in this way makes a lot of sense. Give the user the option to try to abort, but then to optionally change his/her mind and keep going. Or possibly have a third option: break out of the current operation and go back to some primary loop (throw the exception and let it be caught at the main loop). Arguably the problem here is that KeyboardInterrupt is an exception. Perhaps a more classic signal handling structure should be used: when signal received, call function. That function then has the power to raise an exception, which will propagate through whatever code is currently executing. This sort of thing would have all the usual dangers of signal handlers, though; you have NO IDEA what state the program's in, so you have to be ubercareful of what globals you use or change. ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2012-10-25 15:40 +0000 |
| Message-ID | <50895d7b$0$29978$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #32130 |
On Fri, 26 Oct 2012 01:51:43 +1100, Chris Angelico wrote:
> On Thu, Oct 25, 2012 at 12:15 PM, Steven D'Aprano
> <steve+comp.lang.python@pearwood.info> wrote:
>> I don't believe that there is any
>> way to jump back to the line of code that just failed (and why would
>> you, it will just fail again)
>
> There are several reasons to retry something after an exception,
I'm sure there are, but you're taking my point out of context.
Andrea described his problem as *continuing*, not *re-trying*. I
understand that re-trying operations is useful:
while True:
try:
some_operation()
except SomeException:
if not retry():
break # or raise an exception, or return
but I wouldn't describe that as "continuing", as Andrea did. I understand
that as:
try:
operation(1)
operation(2)
operation(3)
operation(4)
# and so forth...
except SomeException:
if retry():
# Magically jump back to the operation that was
# active when the exception occurred.
magic_happens_here()
If you could guarantee that each operation(N) was atomic ("all or
nothing" -- it either succeeds, or has no effect) then such a feature
would be useful. But as far as I know, you can't jump back into a try
block from the except block, and even if you could, what's to stop the
operation from failing again and again and again?
In Andrea's case, the failure he is worried about is "oops, I hit Ctrl-C
when I actually wanted to not hit Ctrl-C", so presumably the failure
wouldn't reoccur if you could jump backwards. But in any case, I can see
no obvious way to make it work.
The python debugger pdb has a "jump" command that allows you to step
backwards and re-execute code under certain conditions, so perhaps it is
not quite impossible.
(I'm tempted to reply that the actual solution to this problem of
accidentally hitting Ctrl-C is "well don't do that then".)
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | "Prasad, Ramit" <ramit.prasad@jpmorgan.com> |
|---|---|
| Date | 2012-10-25 20:59 +0000 |
| Message-ID | <mailman.2866.1351198768.27098.python-list@python.org> |
| In reply to | #32083 |
andrea crotti wrote: > 2012/10/25 Steven D'Aprano <steve+comp.lang.python@pearwood.info>: > > On Wed, 24 Oct 2012 13:51:30 +0100, andrea crotti wrote: > > [snip] > > Without a try...except block, execution will cease after an exception is > > caught, even when using sys.excepthook. I don't believe that there is any > > way to jump back to the line of code that just failed (and why would you, > > it will just fail again) or the next line (which will likely fail because > > the previous line failed). > > > > I think the only way you can do this is to write your own execution loop: > > > > while True: > > try: > > run(next_command()) > > except KeyboardInterrupt: > > if confirm_quit(): > > break > > > > > > Of course you need to make run() atomic, or use transactions that can be > > reverted or backed out of. How plausible this is depends on what you are > > trying to do -- Python's Ctrl-C is not really designed to be ignored. > > > > Perhaps a better approach would be to treat Ctrl-C as an unconditional > > exit, and periodically poll the keyboard for another key press to use as > > a conditional exit. Here's a snippet of platform-specific code to get a > > key press: > > > > http://code.activestate.com/recipes/577977 > > > > Note however that it blocks if there is no key press waiting. > > > > I suspect that you may need a proper event loop, as provided by GUI > > frameworks, or curses. > > > > Ok thanks, but here the point is not to resume something that is going > to fail again, just to avoid accidental kill of processes that take a > long time. Probably needed only by me in debugging mode, but anyway I > can do the simple try/except then, thanks.. On the other hand, if you store state externally (pickle?) maybe you can just restart at the last "check point". That way even if the program dies you can recover on the next run. Ramit Prasad This email is confidential and subject to important disclaimers and conditions including on offers for the purchase or sale of securities, accuracy and completeness of information, viruses, confidentiality, legal privilege, and legal entity disclaimers, available at http://www.jpmorgan.com/pages/disclosures/email.
[toc] | [prev] | [next] | [standalone]
| From | Hans Mulder <hansmu@xs4all.nl> |
|---|---|
| Date | 2012-10-25 17:31 +0200 |
| Message-ID | <50895b4f$0$6931$e4fe514c@news2.news.xs4all.nl> |
| In reply to | #32035 |
On 24/10/12 14:51:30, andrea crotti wrote:
> So I would like to be able to ask for confirmation when I receive a C-c,
> and continue if the answer is "N/n".
>
> I'm already using an exception handler set with sys.excepthook, but I
> can't make it work with the confirm_exit, because it's going to quit in
> any case..
>
> A possible solution would be to do a global "try/except
> KeyboardInterrupt", but since I already have an excepthook I wanted to
> use this. Any way to make it continue where it was running after the
> exception is handled?
>
>
> def confirm_exit():
> while True:
> q = raw_input("This will quit the program, are you sure? [y/N]")
> if q in ('y', 'Y'):
> sys.exit(0)
> elif q in ('n', 'N'):
> print("Continuing execution")
> # just go back to normal execution, is it possible??
> break
>
>
> def _exception_handler(etype, value, tb):
> if etype == KeyboardInterrupt:
> confirm_exit()
> else:
> sys.exit(1)
>
>
> def set_exception_handler():
> sys.excepthook = _exception_handler
I think the trick is to not use an except hook, but trap the
interrupt on a lower level.
This seems to work; I'm not sure how robust it is:
import signal
def handler(signum, frame):
while True:
q = raw_input("This will quit the program, are you sure? [y/N]")
if q[:1] in "yY":
raise KeyboardInterrupt
elif q[:1] in "nN":
print("Continuing execution")
# just go back to normal execution
return
signal.signal(signal.SIGINT, handler)
If you're debugging this on a Unix platform, it may help to know
that you can also kill a process with control-\
Hope this helps,
-- HansM
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2012-10-26 03:02 +1100 |
| Message-ID | <mailman.2850.1351180934.27098.python-list@python.org> |
| In reply to | #32134 |
On Fri, Oct 26, 2012 at 2:31 AM, Hans Mulder <hansmu@xs4all.nl> wrote:
> This seems to work; I'm not sure how robust it is:
>
> import signal
>
> def handler(signum, frame):
> while True:
> q = raw_input("This will quit the program, are you sure? [y/N]")
> if q[:1] in "yY":
> raise KeyboardInterrupt
> elif q[:1] in "nN":
> print("Continuing execution")
> # just go back to normal execution
> return
>
> signal.signal(signal.SIGINT, handler)
>
Yes, that's what I was talking about. You do have to be fairly careful
what you do (for instance, what should happen if the user hits Ctrl-C
during handler()? Default is that it'll raise KeyboardInterrupt
unconditionally), but you have perfect flexibility.
ChrisA
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web