Все ответы на этот вопрос (кроме ответов сумасшедших) говорят об одном и том же: отправьте запрос на консоль и вызовите input(). Это стандартный подход, и я немного удивлен, увидев в одном из комментариев, что это обходной путь. Я сам делаю это уже много лет. Здесь я сообщаю о проблеме с этим подходом, которую я не видел нигде, и уж точно не в этом вопросе.
У меня есть программа для Windows, которая отправляет выходные данные на терминал. При вызове (скажем) из проводника он открывает окно терминала, отправляет выходные данные на терминал, а затем закрывает его. Я добавил параметр командной строки --pause, который имитирует то, что будет делать терминал Windows, если вы поместите паузу в пакетный файл: он запускает программу, затем выводит «Нажмите Enter, чтобы продолжить» и ждет. Таким образом, если программа выдаст предупреждение, пользователь сможет увидеть его до закрытия окна.
Это достигается следующим образом:
- До if __name__ == '__main__':
def console_pause(args):
if args.pause:
input("Press enter to continue") - После и в области действия if __name__ == '__main__':
atexit.register(console_pause, args)
Round-trip yielded identical result
Wrote filename.pkl containing 194128 rows × 7 columns
Wrote filename2.pkl containing 194128 rows × 7 columns
Wrote filename3.pkl containing 194128 rows × 7 columns
Press enter to continue
В ответ нажата клавиша Enter; тогда
Press enter to continueException ignored in atexit callback:
Traceback (most recent call last):
File "scriptname.py", line 611, in console_pause
input("Press enter to continue")
ValueError: I/O operation on closed file.
Думаю, я в общих чертах понимаю, что происходит. Программа завершается, и это приводит к закрытию стандартного ввода до возврата вызова input().
Я никогда раньше этого не замечал, потому что, конечно, при нажатии Enter окно терминала немедленно закрывалось и не показывало мне ошибку. Именно этого я и пытался избежать в первую очередь.
Может ли кто-нибудь объяснить более конкретно, что я делаю неправильно, и предложить альтернативный подход? Я уже вижу, что один ответ — Не выполнять терминальный ввод-вывод при вызове atexit, а другой — Поместить паузу в пакетный файл, а не в программу. Я ищу способ решить проблему, а не переместить ее.
В ответ на комментарий о том, что atexit() является проблемой, и я мог бы с таким же успехом поставить паузу внизу защитного знака __main__: я не согласен. Если программа останавливается с исключением, я хочу, чтобы atexit сработал, потому что в противном случае окно закроется, не дав мне возможности увидеть обратную трассировку.
В ответ на замечание, что именно Windows вызывает сбой стандартного подхода Python: это правда. Но я не согласен с тем, что это проблема X/Y и что мне следует решать ее с помощью решения на уровне ОС (например, паузы в пакетном файле). Я уже отклонил это решение, потому что:
Предположим, мне нужны две паузы: одна в середине выполнения и одна в конце: тогда я мог бы вызвать input() для первого, но мне нужно было бы найти какое-то другое решение для второго. Если оставить в стороне вопросы вкуса, то здесь, как минимум, отсутствует ортогональность. Кроме того, я хочу, чтобы пауза зависела от аргумента командной строки. Приостановка пакетного файла не подойдет.
Очевидно, что проблема заключается в состоянии гонки между CreateProcessEx() и завершением работы интерпретатора Python. И
Я уже упоминал одно из возможных решений: Не выполнять терминальный ввод-вывод при вызове atexit. И это оказалось осуществимо:
if args.pause:
print("Press a key to continue")
msvcrt.getch()