'Python exit() command trigger infinite loop
Greeting all, I encountered infinite loop when running the code below when input option = 3.
def enter_number_only():
print()
print("======================")
print("Enter Number 1-3 only!")
print("======================")
def thank_you_goodbye():
print()
print("======================")
print("Thank You & GoodBye!")
print("======================")
exit()
def retry_main_exit():
while True:
print("1. Retry")
print("2. Back to Main Menu")
print("3. Exit / Quit")
print("=================================")
try:
option = int(input("Please Enter 1 - 3 to Continue: "))
if option == 1:
print("1")
break
elif option == 2:
print("2")
break
elif option == 3:
thank_you_goodbye()
break
else:
enter_number_only()
except:
enter_number_only()
return option
retry_main_exit()
However, if I replaced: (initial code)
elif option == 3:
thank_you_goodbye()
break
to (edited code)
elif option == 3:
print("gg")
break
it will exit the loop smoothly.
Need advice on how to remain the initial code but to be able exit the loop? and seeking for the root cause on this issue.
Many thanks in advance.
Updates: The issue get solved by sharing from @Daniel Corin due to except
clause. The code get fixed with edit below
except TypeError:
enter_number_only()
Solution 1:[1]
Just remove exit
on last line of thank_you_goodbye
function, then it will work smoothly.
def thank_you_goodbye():
print()
print("======================")
print("Thank You & GoodBye!")
print("======================")
exit()
Solution 2:[2]
A number of folks have mentioned a fix by removing exit()
but let's dive into why you are seeing what you're seeing with a simpler example:
In the following code, we first request user input, then we call exit()
which raises SystemExit
, which is then handled by the bare except
clause.
Side note: using bare except
clauses is not recommended. More on that here.
while True:
try:
i = input('input? ')
exit()
except:
print('hey')
We might expect after entering the first user input that the program would loop around to ask for user input again after handling SystemExit
in the except
clause. However, what happens instead is the following:
? python3 test.py
input? 1
hey
input? hey
input? hey
input? hey
input? hey
...infinitely
However, if SystemExit
is handled explicitly, the program also does something we might not expect -- it actually exits, raising a different exception:
while True:
try:
i = input('input? ')
exit()
except SystemExit:
print('hey')
? python3 test.py
input? 1
hey
input? Traceback (most recent call last):
File "/Users/danielcorin/Desktop/test.py", line 3, in <module>
i = input('input? ')
ValueError: I/O operation on closed file.
It turns out that raising SystemExit
closes stdin
(which is needed by the input
function), even if the program itself doesn't exit. So in our first example, after calling exit()
, we have a broken input
function, which raises a ValueError
on the second-N calls.
Example exit()
closing stdin
:
import sys
try:
print(sys.stdin.isatty())
exit()
except SystemExit:
print(sys.stdin.isatty())
? python3 test2.py
True
Traceback (most recent call last):
File "/Users/danielcorin/Desktop/test2.py", line 5, in <module>
exit()
File "/usr/local/Cellar/[email protected]/3.9.1_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/_sitebuiltins.py", line 26, in __call__
raise SystemExit(code)
SystemExit: None
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/danielcorin/Desktop/test2.py", line 7, in <module>
print(sys.stdin.isatty())
ValueError: I/O operation on closed file
We're still in the while loop, so all exceptions (first SystemExit
and then ValueError
repeatedly) are handled by the bare except
clause, so the result is the program prints forever, until we signal our program externally to terminate it. This behavior is the same exhibited by your program when exit()
is called in the thank_you_goodbye
function.
In short, the exit()
call breaks the input
function which leads to an infinite loop due to the bare except
clause.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Nagmat |
Solution 2 | Daniel Corin |