Delay a computation in another thread

Terry Reedy tjreedy at udel.edu
Sat Sep 2 19:53:01 EDT 2017


On 9/2/2017 6:53 AM, Steve D'Aprano wrote:
> I want to delay a computation and then print it, in the REPL (interactive
> interpreter). I have something like this:
> 
> 
> import time
> from threading import Timer
> 
> def do_work():
>      x = 2 + 2
>      print("It is", time.asctime(), "and 2+2 is", x)
> 
> def schedule_work():
>      Timer(60, do_work, ()).start()  # schedule it in one minute
> 
> 
> Is this the right way to do it?
> 
> If I do that, it works, mostly. For example:
> 
> py> schedule_work()
> py> dir(45)  # do other stuff, in the interactive interpreter, for one minute
> ['bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']
> py>
> py> It is Sat Sep  2 20:37:58 2017 and 2+2 is 4
> 
> 
> The problem is that after the message is printed, the REPL's prompt is
> disrupted. This is especially annoying when I'm in the middle of typing a line.
> This is just a cosmetic flaw, but it would be nice if I could tell Python to
> redraw the current line. For example, using _ to indicate the position of the
> cursor, this is what happens now:
> 
> py> class K:
> ...     attribute =It is Sat Sep  2 20:48:39 2017 and 2+2 is 4
> _
> 
> 
> This is what I'd prefer:
> 
> py> class K:
> ...     attribute =It is Sat Sep  2 20:48:39 2017 and 2+2 is 4
> ...     attribute =_

I loaded your code into IDLE editor, hit F5, then interactively in Shell:

 >>> schedule_work()
 >>> It is Sat Sep  2 19:13:44 2017 and 2+2 is 4
"thei is kjlkj jjdkj f jkjkd j"
'thei is kjlkj jjdkj f jkjkd j'

With a 10sec delay, I was near the end of typing the statement after the 
prompt.  When the print came, the partial entry was pushed down to a new 
line.  I think that this is even better than what you asked for.  I 
closed the string and hit return and got the normal echo.

If one is entering a multiple line statement, the whole statement is 
pushed down.

 >>> go()
 >>> It is Sat Sep  2 19:42:10 2017 and 2+2 is 4
a = (
	12,

   IDLE usually keeps input blocks, output blocks, and error blocks 
separated, on separate lines.  Response to input(prompt) is an 
exception.  There is also an ocassional bug that I cannot reproduce yet.
I consider not moving the prompt down a minor bug.
bugs.python.org/issue31331

> The other problem is that if I exit the REPL while a Timer is still active, it
> freezes until the time has run before exiting. I know you can't kill a thread
> from the main thread, but is there a way for the Timer to see that the
> interpreter is shutting down and shut itself down?

If you kill a process from another process, it should die.  It does with 
your code run from IDLE.

On Windows, the background user-code execution process start at 11.x Mb. 
  In Win 10 task manager, background processes are listed separately 
from app windows.  I restored 60 sec delay and added s = 'a'*10000000 
near the top of your code to differentiate a process with your code from 
the default user process.

======================= RESTART: F:\Python\mypy\tem.py 
=======================
 >>> schedule_work()
 >>>   # Hit Restart Shell
=============================== RESTART: Shell 
===============================
 >>>

Restart Shell means kill the current user process and start a new one. 
Watching TackManager while doing so, the 20+Mb process is immediately 
replaced by a default 10+Mb process.  Closing Shell justs kills the 
20+Mb process.

-- 
Terry Jan Reedy




More information about the Python-list mailing list