Главная страница

Учебник Python 3.1. Учебник Python 3. Учебник Python 1 Материал из Викиучебника. Оглавление


Скачать 1.85 Mb.
НазваниеУчебник Python 1 Материал из Викиучебника. Оглавление
АнкорУчебник Python 3.1.pdf
Дата05.04.2017
Размер1.85 Mb.
Формат файлаpdf
Имя файлаУчебник Python 3.1.pdf
ТипУчебник
#4516
страница8 из 13
1   ...   5   6   7   8   9   10   11   12   13
in
?
ValueError
: I/O operation on closed file
Считается хорошей манерой использовать ключевое слово with при работе с файловыми объектами. Преимущество этого способа в том, что файл всегда корректно закрывается после выполнения блока, либо если при выполнении было порождено исключение. Кроме того, получающийся код намного короче, чем эквивалентная форма с блоками try
- finally
:
>>>
with
open
(
'/tmp/workfile'
,
'r'
)
as
f:
... read_data
=
f.read()
>>>
f.closed
True
У объектов-файлов есть ещё несколько дополнительных методов, таких как isatty()
и truncate()
, которые используются не так часто; обратитесь к
Справочнику по библиотеке для более полного обзора по файловым объектам.
Модуль
pickle
Строки могут с лёгкостью быть записаны в файл и прочитаны из файла. В случае чисел нужно применить несколько больше усилий: метод read()
возвращает только строки, которые придётся передать функции вроде int()
, которая принимает строку вида '123'
и возвращает её числовое значение:
123
. Однако если вы намереваетесь сохранить более
55

Учебник Python 3.1: Материал из Викиучебника.
сложные типы данных, такие как списки, словари или экземпляры классов, всё становится несколько запутаннее.
Вместо того чтобы принуждать программиста постоянно писать и отлаживать код для замысловатых типов данных, Python предоставляет стандартный модуль под названием pickle
. Это замечательный модуль, который может принять любой объект
Python (даже некоторые формы кода на Python!) и конвертировать его в строковое представление: этот процесс называется консервацией (pickling). Восстановление объекта из его строкового представления называется расконсервацией (unpickling): строка, описывающая объект, может быть сохранена в файл, добавлена к некоторым данным, или отослана через соединение по сети на удаленный компьютер.
[47]
Если у вас есть некоторый объект x
и объект файла f
, открытый на запись в двоичном режиме (binary mode, с параметром 'wb'), простейший способ законсервировать объект требует одной-единственной строки кода:
pickle
.dump(x
,
f)
Чтобы снова расконсервировать объект, при условии что f
— объект файла, открытого для чтения (так же в двоичном режиме, с параметром 'rb'):
x
=
pickle
.load(f)
(Существуют варианты выполнения этих операций, применяемые при расконсервации нескольких объектов или когда вам требуется записать консервированные данные в файл; обратитесь к документации по модулю pickle из
Справочника по библиотеке
.)
pickle
— стандартный способ для создания объектов Python, которые могут быть повторно использованы другими программами или будущими версиями этой же программы; для них есть технический термин — устойчивый объект (persistent object).
Поскольку pickle используется часто, многие авторы расширений для Python заботятся о том, чтобы новые типы данных, такие как матрицы, могли быть корректно законсервированы и расконсервированы.
Ошибки и исключения
До этого момента сообщения об ошибках лишь упоминались, но если вы пробовали примеры на практике — возможно, вы уже видели некоторые. Существует (как минимум) два различимых вида ошибок: синтаксические ошибки (syntax errors) и исключения (exceptions).
Синтаксические ошибки
Синтаксические ошибки, также известные как ошибки разбора кода (парсинга, parsing) — вероятно, наиболее привычный вид жалоб компилятора, попадающихся вам при изучении
Python:
>>>
while
True
print
(
'Hello world'
)
File
""
,
line
1
,
in
?
while
True
print
(
'Hello world'
)
^
SyntaxError
: invalid syntax
Парсер
[48]
повторно выводит ошибочную строку и отображает небольшую «стрелку», указывающую на самую первую позицию в строке, где была обнаружена ошибка. Причина ошибки (или по крайней мере место обнаружения) находится в символе
[49]
,
56

Учебник Python 3.1: Материал из Викиучебника.
предшествующем указанному: в приведённом примере ошибка обнаружена на месте вызова функции print()
, поскольку перед ним пропущено двоеточие (
':'
). Также здесь выводятся имя файла и номер строки, благодаря этому вы знаете в каком месте искать, если ввод был сделан из сценария.
Исключения
Даже если выражение или оператор синтаксически верны, они могут вызвать ошибку при попытке их исполнения. Ошибки, обнаруженные при исполнении, называются исключениями(exceptions). Они не фатальны: позже вы научитесь перехватывать их в программах на Python. Большинство исключений, правда, как правило, не обрабатываются программами и приводят к сообщениям об ошибке, таким как следующие:
>>>
10
* (
1
/
0
)
Traceback (most recent call last):
File
""
,
line
1
,
in
?
ZeroDivisionError
: int division
or
modulo by zero
>>>
4
+ spam*
3
Traceback (most recent call last):
File
""
,
line
1
,
in
?
NameError
: name
'spam'
is
not
defined
>>>
'2'
+
2
Traceback (most recent call last):
File
""
,
line
1
,
in
?
TypeError
: coercing to Unicode: need string
or
buffer
,
int found
Последняя строка сообщения об ошибке описывает произошедшее. Исключения представлены различными типами и тип исключения выводится в качестве части сообщения: в примере это типы
ZeroDivisionError
,
NameError и
TypeError
. Часть строки, описывающая тип исключения — это имя произошедшего встроенного исключения. Такое утверждение верно для всех встроенных исключений, но не обязано быть истинным для исключений, определённых пользователем (однако, само соглашение — довольно полезное). Имена стандартных исключений — это встроенные идентификаторы (не ключевые слова).
Оставшаяся часть строки описывает детали произошедшего на основе типа исключения, которое было его причиной.
Предшествующая часть сообщения об ошибке показывает контекст, где произошло исключение, в форме стека вызовов. В общем случае она содержит стек, состоящий из списка строк исходного кода; тем не менее, в неё не войдут строки, прочитанные из стандартного ввода.
В разделе
Встроенные исключения
Справочника по библиотеке вы найдёте список встроенных исключений и их значений.
Обработка исключений
Существует возможность написать код, который будет перехватывать избранные исключения. Посмотрите на представленный пример, в котором пользователю предлагают вводить число до тех пор, пока оно не окажется корректным целым. Тем не менее, пользователь может прервать программу (используя сочетание клавиш Control-C или какое-либо другое, поддерживаемое операционной системой); заметьте — о вызванном пользователем прерывании сигнализирует исключение
KeyboardInterrupt
57

Учебник Python 3.1: Материал из Викиучебника.
>>>
while
True
:
try
:
... x
=
int
(
input
(
"Введите, пожалуйста, число: "
))
break
except
ValueError
:
print
(
"Ой! Это некорректное число. Попробуйте ещё раз..."
)
Оператор try работает следующим образом:

В начале исполняется блок
try
(операторы между ключевыми словами try и except
).

Если при этом не появляется исключений, блок
except
не выполняется и оператор try заканчивает работу.

Если во время выполнения блока try было возбуждено какое-либо исключение, оставшаяся часть блока не выполняется. Затем, если тип этого исключения совпадает с исключением, указанным после ключевого слова except
, выполняется блок except
, а по его завершению выполнение продолжается сразу после оператора try-except

Если порождается исключение, не совпадающее по типу с указанным в блоке except
— оно передаётся внешним операторам try
; если ни одного обработчика не найдено, исключение считается необработанным (unhandled exception), и выполнение полностью останавливается и выводится сообщение, схожее с показанным выше.
Оператор try может иметь более одного блока except
— для описания обработчиков различных исключений. При этом будет выполнен максимум один обработчик.
Обработчики ловят только те исключения, которые возникают внутри соответствующего блока try
, но не те, которые возникают в других обработчиках этого же самого оператора try-except
. Блок except может указывать несколько исключений в виде заключённого в скобки кортежа, например:
except
(
RuntimeError
,
TypeError
,
NameError
):
pass
В последнем блоке except можно не указывать имени (или имён) исключений. Тогда он будет действовать как обработчик группы исключений. Используйте эту возможность с особой осторожностью, поскольку таким образом он может с лёгкостью перехватить и фактическую ошибку программиста! Также такой обработчик может быть использован для вывода сообщения об ошибке и порождения исключения заново (позволяя при этом обработать исключение коду, вызвавшему обработчик):
import
sys
try
:
f
=
open
(
'myfile.txt'
)
s
=
f.
readline
()
i
=
int
(s.strip())
except
IOError
as
err:
print
(
"I/O error: {0}"
.format(err))
except
ValueError
:
print
(
"Не могу преобразовать данные в целое."
)
except
:
print
(
"Неожиданная ошибка:"
,
sys
.exc_info()[
0
])
raise
58

Учебник Python 3.1: Материал из Викиучебника.
У оператора try-except есть необязательный блок
else
, который, если присутствует, должен размещаться после всех блоков except
. Его полезно использовать при наличии кода, который должен быть выполнен, если блок try не породил исключений. Например:
for
arg
in
sys
.argv[
1
:]:
try
:
f
=
open
(arg
,
'r'
)
except
IOError
:
print
(
'не могу открыть'
,
arg)
else
:
print
(arg
,
'содержит'
,
len
(f.readlines())
,
'строк'
)
f.close()
Использование блока else предпочтительнее, чем добавление дополнительного кода к блоку try
, поскольку исключает неожиданный перехват исключения, которое появилось не по причине выполнения кода, защищенного оператором try-except
При появлении исключения, оно может иметь ассоциированное значение, также известное как аргумент (argument) исключения. Присутствие и тип аргумента зависят от типа самого исключения.
В блоке except можно указать переменную, следующую за именем исключения.
Переменная связывается с экземпляром исключения, аргументы которого хранятся в
instance.args
. Для удобства, экземпляр исключения определяет метод
__str__()
, так что вывод аргументов может быть произведён явно, без необходимости отсылки к
.args
Таким образом, вы также можете создать/взять экземпляр исключения перед его порождением и добавить к нему атрибуты по желанию.
>>>
try
:
raise
Exception
(
'spam'
,
'eggs'
)
except
Exception
as
inst:
print
(
type
(inst))
# экземпляр исключения
print
(inst.args)
# аргументы хранятся в .args
print
(inst)
# __str__ позволяет вывести args явно,
# но может быть переопределён в подклассах
исключения
... x
,
y
=
inst
# распаковка args
print
'x ='
,
x
print
'y ='
,
y
<
class
'Exception'
>
(
'spam'
,
'eggs'
)
(
'spam'
,
'eggs'
)
x
=
spam y
=
eggs
Если у исключения есть аргументы, они выводится в качестве последней («детальной») части сообщения о необработанном исключении.
Обработчики исключений перехватывают не только исключения, появившиеся прямо в блоке try
, но также и возбужденные внутри функций, которые были в блоке try вызваны
(даже неявно). Например:
>>>
def
this_fails():
... x
=
1
/
0
>>>
try
:
... this_fails()
59

Учебник Python 3.1: Материал из Викиучебника.
except
ZeroDivisionError
as
err:
print
(
'Перехват ошибки времени исполнения:'
,
err)
Перехват ошибки времени исполнения: integer division
or
modulo by zero
Порождение исключений
Оператор raise позволяет программисту принудительно породить исключение. Например:
>>>
raise
NameError
(
'ПриветТам'
)
Traceback (most recent call last):
File
""
,
line
1
,
in
?
NameError
: ПриветТам
Единственный аргумент оператора raise определяет исключение, которое нужно возбудить. Им может быть либо экземпляр исключения, либо класс исключения (класс, дочерний к классу
Exception
).
Если вам нужно определить, было ли возбуждено исключение, не перехватывая его — упрощённая форма оператора raise позволит возбудить исключение заново:
>>>
try
:
raise
NameError
(
'ПриветТам'
)
except
NameError
:
print
(
'Исключение пролетело мимо!'
)
raise
Исключение пролетело мимо
!
Traceback (most recent call last):
File
""
,
line
2
,
in
?
NameError
: ПриветТам
Исключения, определённые пользователем
В программах можно определять свои собственные исключения — посредством создания нового класса исключения. В общем случае, исключения должны быть унаследованы от класса
Exception
: явно или неявно. Например:
>>>
class
MyError(
Exception
):
def
__init__
(
self
,
value):
self
.value
=
value
def
__str__
(
self
):
return
repr
(
self
.value)
>>>
try
:
raise
MyError(
2
*
2
)
except
MyError
as
e:
print
(
'Поймано моё исключение со значением:'
,
e.value)
Поймано моё исключение со значением:
4
>>>
raise
MyError(
'ой!'
)
Traceback (most recent call last):
File
""
,
line
1
,
in
?
__main__
.MyError:
'ой!'
В этом примере был перегружен конструктор по умолчанию
__init__()
класса
Exception
Новое поведение отличается лишь созданием нового атрибута value и заменяет поведение по умолчанию, при котором создаётся атрибут args
Классы исключений могут определять любые действия, которые могут делать все другие классы. Однако, обычно их внутренняя структура довольно проста, и предоставляет лишь некоторые атрибуты, позволяющие обработчикам исключений выяснить информацию об
60

Учебник Python 3.1: Материал из Викиучебника.
ошибке подробно. При создании модуля, который может породить различные ошибки, обычной практикой будет создание базового класса для исключений, определённых в этом модуле, и подклассов для различных ошибочных состояний:
class
Error(
Exception
):
"""Базовый класс для всех исключений в этом модуле."""
pass
class
InputError(Error):
"""Исключение порождается при ошибках при вводе.
Атрибуты:
expression -- выражение на вводе, в котором обнаружена ошибка message -- описание ошибки """
def
__init__
(
self
,
expression
,
message):
self
.expression
=
expression self
.message
=
message
class
TransitionError(Error):
"""Порождается, когда операция пытается выполнить неразрешённый переход из одного состояния в другое.
Attributes:
previous -- состояние в начале перехода next -- новое состояние, попытка принять которое была принята message -- описание, по какой причине такой переход невозможен """
def
__init__
(
self
,
previous
,
next
,
message):
self
.previous
=
previous self
.next
=
next self
.message
=
message
Большинство исключений имеет имя, заканчивающееся на «
Error
», подобно стандартным исключениям.
Много стандартных модулей определяют собственные исключения, сообщающие об ошибках, которые могут появиться в определяющих их модулях. Больше информации о классах представлено в главе 1.10,
Классы
Определение действий при подчистке
У оператора try есть другой необязательный блок, предназначенный для операций подчистки, которые нужно выполнить независимо от условий:
>>>
try
:
raise
KeyboardInterrupt
finally
:
print
(
'Прощай, мир!'
)
Прощай
,
мир
!
Traceback (most recent call last):
File
""
,
line
2
,
in
?
KeyboardInterrupt
Блок
finally
исполняется всегда, когда интерпретатор покидает оператор try
, независимо — были исключения или нет. Если в блоке try появилось исключение, которое
61

Учебник Python 3.1: Материал из Викиучебника.
не было обработано в блоке except
(или появилось в самих блоках except или else
) — оно порождается заново после выполнения блока finally
. Также блок finally исполняется
«по пути наружу», если какой-либо другой блок оператора try был покинут за счёт одного из операторов: break
, continue или return
. Более сложный пример:
>>>
def
divide(x
,
y):
try
:
... result
=
x / y
except
ZeroDivisionError
:
print
(
"деление на ноль!"
)
1   ...   5   6   7   8   9   10   11   12   13


написать администратору сайта