1

What is the best way to implement an infinite loop in Python, such that a given function is run again and again until the user presses a key? I can think of a couple of ways of doing this, one of which involves Ctrl-C, and the other involves threading: both of which seem extremely hacky, and leave me with the feeling that I'm missing something blindingly obvious.

Here's a minimal working example of the Ctrl-C method:

def run():
    my_object = MyClass()
    my_object.lay_the_table()
    print("Telling my_object to keep refreshing... Use Ctrl-C to stop.")
    while True:
        my_object.refresh()
    my_object.tidy_away()

if __name__ == "__main__":
    run()

The failings of this method are obviously:

  • The tidy_away() method is never called.
  • I can't imagine it's ever good practice to invite the user to kill the program manually.

But what's a better way?


I'm really surprised that I can't find a similar question to this one - for Python - on Stack Overflow. Then again, it might well be that I'm just not using the search function properly! Happy to have this question marked as a duplicate if it points me to a solution.

wjandrea
  • 28,235
  • 9
  • 60
  • 81
Tom Hosker
  • 526
  • 2
  • 17
  • 1
    this may help [how-to-stop-an-infinite-loop-safely-in-python](https://stackoverflow.com/questions/32922909/how-to-stop-an-infinite-loop-safely-in-python) – deadshot Aug 03 '20 at 15:05
  • 1
    i think your issue is really just detecting a keypress: https://stackoverflow.com/questions/24072790/detect-key-press-in-python/32386410 – vencaslac Aug 03 '20 at 15:07
  • 2
    If you do want something driven by ctrl-C, why not just `try: [your infinite loop]` `except KeyboardInterrupt: my_object.tidy_away()` – alani Aug 03 '20 at 15:09
  • 1
    The best way to make sure the line is called is to use `finally` instead of `except`. – Klaus D. Aug 03 '20 at 15:27

2 Answers2

2

Using Ctrl+C is fine, but you should use exception handling. Catch KeyboardInterrupt, and use finally to define cleanup actions.

def run():
    my_object = MyClass()
    my_object.lay_the_table()
    print("Telling my_object to keep refreshing... Use Ctrl-C to stop.")
    try:
        while True:
            my_object.refresh()
    except KeyboardInterrupt:
        pass
    finally:
        my_object.tidy_away()

if __name__ == "__main__":
    run()

Since Ctrl+C sends an interrupt, this is actually probably the easiest way to do it.

wjandrea
  • 28,235
  • 9
  • 60
  • 81
1

To implement an infinitely looping loop that exits the loop if you meet a condition, simply:

while True:
    run()
    if exitcondition == True:
        break

this will loop the function infinitely until the exit condition is met, then it will exit the loop. if you want the program to end after the exit condition, replace "break" with quit().

Andrew C
  • 137
  • 2
  • 10
  • 1
    +1, but I hope you'll forgive me giving you a couple of tips. (1) Your solution assumes that getting `exitcondition` to turn `True` at the desired moment is straightforward, but this is precisely the difficult part of the problem. (2) I think your code would be more elegant if your wrote something more like: `while not exitcondition: \\ run()`. Mine's shorter, if nothing else! – Tom Hosker Aug 03 '20 at 15:29
  • 1
    `exitcondition == True` is redundant. Just use `if exitcondition:` – wjandrea Aug 03 '20 at 15:41