easiest way to pause a command-line python program?

2.6k views Asked by At

Let's say I have a python program that is spitting out lines of text, such as:

while 1:
  print "This is a line"

What's the easiest way to allow one to press a key on the keyboard to pause the loop, then to resume if pressed again---but if nothing is pressed it should just continue on automatically?

I'm hoping I don't have to go into something like curses to get this!

3

There are 3 answers

0
ChristopheD On BEST ANSWER

You could try this implementation for Linux / Mac (and possible other Unices) (code attribution: found on ActiveState Code Recipes).

On Windows you should check out msvcrt.

import sys, termios, atexit
from select import select

# save the terminal settings
fd = sys.stdin.fileno()
new_term = termios.tcgetattr(fd)
old_term = termios.tcgetattr(fd)

# new terminal setting unbuffered
new_term[3] = (new_term[3] & ~termios.ICANON & ~termios.ECHO)

# switch to normal terminal
def set_normal_term():
    termios.tcsetattr(fd, termios.TCSAFLUSH, old_term)

# switch to unbuffered terminal
def set_curses_term():
    termios.tcsetattr(fd, termios.TCSAFLUSH, new_term)

def putch(ch):
    sys.stdout.write(ch)

def getch():
    return sys.stdin.read(1)

def getche():
    ch = getch()
    putch(ch)
    return ch

def kbhit():
    dr,dw,de = select([sys.stdin], [], [], 0)
    return dr <> []

Implementing what you're looking for would then become something like this:

atexit.register(set_normal_term)
set_curses_term()

while True:
    print "myline"
    if kbhit():
        print "paused..."
        ch = getch()
        while True
            if kbhit():
                print "unpaused..."
                ch = getch()
                break
0
waterproof On

When you press Ctrl+C, a KeyboardInterrupt exception gets raised in your program. You can catch that exception to create the behavior you want - for instance, to pause the program and resume after 5s:

import time

while True:
     try:
         # This is where you're doing whatever you're doing
         print("This is a line")
     except KeyboardInterrupt:
         print("Paused! Ctrl+C again within 5 seconds to kill program")
         # A second KeyboardInterrupt that happens during this sleep will
         # not be caught, so it will terminate the program
         time.sleep(5)
         print("Continuing...")

Or to pause the program indefinitely until the user hits 'enter':

while True:
     try:
         # This is where you're doing whatever you're doing
         print("This is a line")
     except KeyboardInterrupt:
         print("Interrupted!")
         input("Press enter to continue, or Ctrl+C to terminate.")
         print("Continuing...")

If you want to catch a second KeyboardInterrupt as well and do something fancy with that, you can do so by nesting try/except blocks, though I wouldn't really recommend that - it's a good idea to allow a string of KeyboardInterrupts to terminate the program.

0
Brian Wisti On

The easiest way for me, assuming I was working in bash, would be to hit Control-Z to suspend the job, then use the 'fg' command to restore it when I was ready. But since I don't know what platform you're using, I'll have to go with using ChristopheD's solution as your best starting point.