Мне известно, что sys.В документации exc_info говорится, что нужно проявлять осторожность при работе с объектами трассировки, но я все еще не уверен, насколько безопасны или небезопасны некоторые случаи. Кроме того, в документации говорится: «Предупреждение: не делайте этого!», За которым сразу следует «Примечание: на самом деле, все в порядке», что еще больше меня смущает.
В любом случае, документы и « Почему необходимо явно удалять трассировку sys.exc_info () в Python? » (ответ Алекса Мартелли), похоже, подразумевают его единственные локальные переменные, которые ссылка на присвоенное им значение трассировки, вызывающее проблему.
Это оставляет мне несколько вопросов:
Не стесняйтесь сказать мне, где мои выводы или предположения ошибочны, поскольку я несколько раз убеждал себя в вере или неверии в свои собственные утверждения, когда писал это :).
Хоть я и хотел бы получить ответы на свои конкретные примеры, я также прошу общих советов, знаний или военных историй о том, как безопасно справляться с трассировкой в более эзотерических ситуациях (например, вы должны запустить цикл и захотеть чтобы накапливать любые возникшие исключения, вам необходимо создать новый поток и сообщить о любых возникших в нем исключениях, вам необходимо создать закрытие и обратные вызовы, а также сообщить о возбужденных исключениях и т. д.).
Пример 1: внутренняя функция, выполняющая обработку ошибок.
def DoWebRequest():
thread, error_queue = CreateThread(ErrorRaisingFunc)
thread.start()
thread.join()
if not error_queue.empty():
# Purposefully not calling error_queue.get() for illustrative purposes
print 'error!'
def CreateThread(func):
error_queue = Queue.Queue()
def Handled():
try:
func()
except Exception:
error_queue.put(sys.exc_info())
thread = threading.Thread(target=Handled)
return thread, error_queue
Вызывает ли закрытие Handled ()
какое-либо возбужденное исключение для ссылки error_queue
и приводит к циклической ссылке, потому что error_queue
также содержит трассировку? Достаточно ли удаления трассировки из error_queue
(т.е. вызова .get ()
), чтобы исключить циклическую ссылку?
Пример 2: долгоживущий объект в области exc_info, или возврат exc_info
long_lived_cache = {}
def Alpha(key):
expensive_object = long_lived_cache.get(key)
if not expensive_object:
expensive_object = ComputeExpensiveObject()
long_lived_cache[key] = expensive_object
exc_info = AlphaSub(expensive_object)
if exc_info:
print 'error!', exc_info
def AlphaSub(expensive_object):
try:
ErrorRaisingFunc(expensive_object)
return None
except Exception:
return sys.exc_info()
Имеет ли вызванное исключение AlphaSub ()
ссылку на own_object
, и, поскольку Road_object
кэширован, трассировка никогда не исчезает ? Если да, то как разорвать такой цикл?
В качестве альтернативы, exc_info
содержит кадр стека Alpha
, а кадр стека Alpha
содержит ссылку на exc_info
, в результате получается циклическая ссылка. Если да, то как разорвать такой цикл?