Ответ 1
Python 3 (обновление до исходного ответа):
В Python 3 совет, цитируемый в вопросе, был удален из документации Python. Мой первоначальный ответ (который следует) применяется только к версиям Python, которые включают цитату в их документации.
Python 2:
Сборщик мусора Python, в конце концов, найдет и удалит круговые ссылки, подобные тому, который создан путем ссылки на стек трассировки изнутри одного из самих стековых фреймов, поэтому не возвращайтесь и не переписывайте свой код. Но, продвигаясь вперед, вы можете следовать советам
http://docs.python.org/library/sys.html
(где он документирует exc_info()
) и скажет:
exctype, value = sys.exc_info()[:2]
когда вам нужно получить исключение.
Еще две мысли:
Во-первых, почему вы используете exc_info()
вообще?
Если вы хотите поймать исключение, вы не должны просто сказать:
try:
...
except Exception as e: # or "Exception, e" in old Pythons
... do with with e ...
вместо того, чтобы обманывать объекты внутри модуля sys
?
Вторые: Хорошо, я дал много советов, но на самом деле не ответил на ваш вопрос.: -)
Почему создается цикл? Ну, в простых случаях цикл создается, когда объект ссылается на себя:
a = [1,2,3]
a.append(a)
Или, когда два объекта относятся друг к другу:
a = [1,2,3]
b = [4,5,a]
a.append(b)
В обоих случаях, когда функция заканчивается, значения переменных все равно будут существовать, потому что они заблокированы в объявлении отсчета: ни один не может уйти, пока другой не уйдет первым! Только современный сборщик мусора Python может разрешить это, со временем заметив цикл и сломав его.
И поэтому ключом к пониманию этой ситуации является то, что объект "трассировка" - третья вещь (по индексу № 2), возвращаемая exc_info()
- содержит "фрейм стека" для каждой функции, которая была активна, когда исключение было называется. И эти фреймы стека не являются "мертвыми" объектами, показывающими, что было истинным при вызове execption; кадры все еще живы! Функция, которая поймала исключение, все еще жива, поэтому ее стек кадров является живым существом, все еще растущим и теряющим ссылки на переменные, поскольку его код выполняет обработку исключения (и делает все, что он делает по мере завершения предложения "except", и идет о его работе).
Итак, когда вы говорите t = sys.exc_info()[2]
, один из этих кадров стека внутри трассировки - кадр, фактически принадлежащий самой функции, которая в настоящее время работает, теперь имеет переменную в ней с именем t
, которая указывает на сам кадр стека, создавая цикл, подобный тем, которые я показал выше.