08.07.2024
Input
Когда в коде вызывается функция input()
, программа останавливается и ждет пользовательского ввода. Это встроенная функция
Функция input()
конвертирует ввод в строку по умолчанию (python2 задает тип данных автоматически и не требует явно задавать тип (если в ответ на input()
введешь число, то получится int
, а если строку, то str
))
Еще в Python2 была функция raw_input()
, она как раз работает как input()
в Python3
Эта функция возвращает строку
>>> input("-> ")
-> test
'test'
Как видно единственно возможный опциональный параметр (prompt) выводится перед приглашением к вводу без переноса строки
>>> input("multiline\nprompt: ")
multiline
prompt: string
'string'
Чтобы твоя программа с использованием функции input()
была эффективной:
- Используй понятный prompt, например вместо 'введите значение' напиши 'укажите свой возраст'. Это позволит избежать конфузов при использовании твоей программы
- Проверяй пользовательский ввод. Лучше сразу убедиться что пользовательский ввод не проходит по требованиям чем вывалиться в ошибку в конце работы программы из-за некорректного ввода пользователя. Проверь что числовое значение входит в допустимые рамки (наверное если на запрос возраста пользователь ввел
220
, то что-то не так), убедись что текстовый ввод по размеру не превышает лимит, убедись что ввод не пустой (ну и вдовесок что на запрос числа мы не получили строку) - Используй блоки
try-except
для обработки некорректного пользовательского ввода и предоставь пользователю информативный текст ошибки чтобы он исправил свой ввод
Exceptions
В Python все исключения это экземпляры класса который отнаследован от класса BaseException
Классы могут наследоваться друг от друга. Так ZeroDivisionError происходит от ArithmeticError, который происходит от Exception, который происходит от BaseException
Два не связанных общим родителем класса не являются эквивалентными, даже если у них одинаковое имя
То есть если мы укажем в except
имя родительского класса, например LookupError
, то нам не важно произошел у нас IndexError
или KeyError
Ниже код демонстрирующий, что под except B
подпадает и сам B
, и его сын, и его внук
>>> class B(Exception):
... pass
...
>>> class C(B):
... pass
...
>>> class D(C):
... pass
...
>>> for cls in [B, C, D]:
... try:
... raise cls()
... except B:
... print("B: " + str(cls))
...
B: <class '__main__.B'>
B: <class '__main__.C'>
B: <class '__main__.D'>
Встроенные классы исключений могут быть родительскими для классов определенных программистом. Для описания своих классов исключений рекомендуется наследоваться от класса Exception
, а не от BaseException
BaseException - это базовый класс для всех встроенных исключений
Exception - это базовый класс для всех нефатальных исключений и он наследуется от BaseException (именно от Exception нужно наследовать свои кастомные исключения)Пример: исключение KeyboardInterrupt вызывается когда пользователь завершает нашу программу с помощью
Control-C
, так как это фатальное исключение, то оно наследуется от BaseException, а не от Exception
Могут быть обработаны все перечисленные исключения (а не только нефатальные)
Пример подтверждающий это:
>>> import time
>>> try:
... time.sleep(60)
... except KeyboardInterrupt:
... time.ctime()
... time.sleep(5)
... time.ctime()
... print("KeyboardInterrupt: CTRL-C was pressed")
...
^C'Tue Jul 9 02:13:25 2024'
'Tue Jul 9 02:13:30 2024'
KeyboardInterrupt: CTRL-C was pressed
Иерархия наследования классов исключений:
BaseException
├── BaseExceptionGroup
├── GeneratorExit
├── KeyboardInterrupt
├── SystemExit
└── Exception
├── ArithmeticError
│ ├── FloatingPointError
│ ├── OverflowError
│ └── ZeroDivisionError
├── AssertionError
├── AttributeError
├── BufferError
├── EOFError
├── ExceptionGroup [BaseExceptionGroup]
├── ImportError
│ └── ModuleNotFoundError
├── LookupError
│ ├── IndexError
│ └── KeyError
├── MemoryError
├── NameError
│ └── UnboundLocalError
├── OSError
│ ├── BlockingIOError
│ ├── ChildProcessError
│ ├── ConnectionError
│ │ ├── BrokenPipeError
│ │ ├── ConnectionAbortedError
│ │ ├── ConnectionRefusedError
│ │ └── ConnectionResetError
│ ├── FileExistsError
│ ├── FileNotFoundError
│ ├── InterruptedError
│ ├── IsADirectoryError
│ ├── NotADirectoryError
│ ├── PermissionError
│ ├── ProcessLookupError
│ └── TimeoutError
├── ReferenceError
├── RuntimeError
│ ├── NotImplementedError
│ └── RecursionError
├── StopAsyncIteration
├── StopIteration
├── SyntaxError
│ └── IndentationError
│ └── TabError
├── SystemError
├── TypeError
├── ValueError
│ └── UnicodeError
│ ├── UnicodeDecodeError
│ ├── UnicodeEncodeError
│ └── UnicodeTranslateError
└── Warning
├── BytesWarning
├── DeprecationWarning
├── EncodingWarning
├── FutureWarning
├── ImportWarning
├── PendingDeprecationWarning
├── ResourceWarning
├── RuntimeWarning
├── SyntaxWarning
├── UnicodeWarning
└── UserWarning
Try Except
В Python есть два вида ошибок:
- синтаксические - возникает на этапе парсинга кода
- логические - исключения возникающие во время работы кода (и они не фатальны)
Имена встроенных исключений это встроенные идентификаторы, а не зарезервированные ключевые слова (значит можно и переопределить)
Конструкция try-except
:
- Блок
try
позволяет запустить некий код - Блок
except
позволяет обработать ошибку возникшую при работе кода из блокаtry
. Принимает на вход либо класс исключения, либо кортеж классов исключений (если хочешь перечислить несколько). Секцияexcept
может быть указана столько раз, сколько нужно (прям подряд). Если ни один except не подошел, то получится unhandled exception и приложение будет остановлено с ошибкой - Блок
else
запустит код если ошибок в блокеtry
не возникло - Блок
finally
запустит код независимо от возникновения ошибок в блокеtry
Внутри except
задается имя класса исключения, будут обработаны также все производные от указанного класса (но не наоборот). То есть когда мы указываем BaseException, то под это условие подпадают вообще все исключения, а если указываем ArithmeticError, то будут обработаны только FloatingPointError, OverflowError и ZeroDivisionError
Будут обработаны не только исключения произошедшие непосредственно внутри блока try
, но и исключения произошедшие внутри функций, вызванных внутри try
Если произойдет исключение внутри секции except
, то будет получена цепочка исключений
>>> try:
... 1 / 0
... except ZeroDivisionError() as err: # из-за скобок около имени класса произойдет исключение
# потому что скобками мы вызываем конструктор и получаем экземпляр класса
# а без скобок передаем идентификатор класса
... print("Handling run-time error:", err)
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ZeroDivisionError: division by zero
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 3, in <module>
TypeError: catching classes that do not inherit from BaseException is not allowed
Raise
Ключевое слово raise
позволяет искуственно стриггерить указанное исключение
>>> raise KeyboardInterrupt
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyboardInterrupt
>>> raise BrokenPipeError
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
BrokenPipeError
>>> raise BaseException
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
BaseException
Будет вызван конструктор указанного класса (туда можно передать аргументы)
Форма
raise ValueError
это сахар для полной записиraise ValueError()
No Comments