Я пытаюсь настроить свой скрипт Python, чтобы пользователь мог завершить программу, однако программа должна сначала завершить то, что она делает. У меня настроен следующий код:
import sys
import keyboard
import time
prepareToStop = 0;
try:
while prepareToStop == 0:
#Program code here
print(prepareToStop)
time.sleep(0.1)
except KeyboardInterrupt:
prepareToStop = 1
print("\nProgram will shut down after current operation is complete.\n")
print("Program shutting down...")
sys.exit()
Однако программа по-прежнему выходит из цикла, как только получено сообщение KeyboardInterrupt. Я видел совет, что это можно исправить, поместив «попробовать, кроме» внутри цикла while, однако это приводит к тому, что программа вообще не может обнаружить KeyboardInterrupt.
Я попробовал это с помощью Windows, и решение @tdelaney работает
Ваш цикл while не завершится, так как в вашем операторе try нет ошибки. Вам нужен оператор выхода в цикле while или просто переместите оператор try внутри цикла while, как сказал @tdelaney
@Pruthvi - Идея состоит в том, что пользователь нажимает ctrl-c для создания прерывания клавиатуры.
Независимо от того, где вы поместите try-except, KeyboardInterrupt прервет по крайней мере часть вашего кода. Вам нужно будет использовать модуль signal, чтобы заменить генерацию этого исключения установкой флага prepareToStop.
@tdelaney Я переместил try/except во время, но результат был тот же. Я также обнаружил, что если я удаляю строку «prepareToStop = 1», цикл начинается сначала, когда срабатывает KeyboardInterrupt. Я думаю, что это настоящая причина проблемы, но я все еще не уверен, как это предотвратить.
Print(prepareToStop) ничего вам не скажет, потому что вы делаете это сразу после того, как проверите, что это 0.
Если я правильно понимаю вашу проблему, возможно, вам поможет threading. Обратите внимание, как end do something появляется даже после KeyboardInterrupt.
Обновлено: я поместил t.join() в try
import sys
import time
import threading
def do_something(prepareToStop):
print(prepareToStop)
time.sleep(1)
print('end do something')
prepareToStop = 0
while prepareToStop == 0:
t = threading.Thread(target=do_something, args=[prepareToStop])
try:
t.start()
t.join() # wait for the threading task to end
except KeyboardInterrupt:
prepareToStop = 1
print("\nProgram will shut down after current operation is complete.\n")
print('will not appear for last run')
print("Program shutting down...")
sys.exit()
Пример вывода:
0
end do something
will not appear for last run
0
^C
Program will shut down after current operation is complete.
will not appear for last run
Program shutting down...
end do something
Попробуйте еще раз с моим Edit: t.join() в разделе try лучше
Прерывание клавиатуры, которое вы пытались использовать, работает как любое системное прерывание и немедленно переходит к блоку исключений, не возвращаясь туда, где оно было, когда произошло прерывание. Вы можете убедиться в этом, используя отладчик в вашей среде IDE (например, нажмите F5 в VSCODE).
Приведенный ниже код работает так, как вы хотите, но пользователь должен удерживать нажатой клавишу ESC на клавиатуре, чтобы он был захвачен из программы в нужное время.
import sys
import keyboard
import time
prepareToStop = 0;
while prepareToStop == 0:
if keyboard.is_pressed('Esc'):
prepareToStop = 1
print("\nProgram will shut down after current operation is complete.\n")
#Program code here
print('Sleeping 5 sec - hold the ESC key for some time to exit')
time.sleep(5)
print('This prints only after the delay')
#end code here
print(prepareToStop)
time.sleep(0.1)
print("Program shutting down...")
sys.exit()
И тогда я бы рекомендовал изменить на это:
import sys
import keyboard
import time
while not keyboard.is_pressed('Esc'):
#Program code here
print('Sleeping 5 sec - hold the ESC key for some time to exit')
time.sleep(5)
print('This prints only after the delay')
#end code here
time.sleep(0.1)
print("Program shutting down...")
sys.exit()
Приведенное выше решение не лучше, чем использование потоков, но оно намного проще.
Перемещение try/кроме внутри while сработало для меня. Я запускаю линукс. Его возможные Windows отличаются.