Переменный выпуск после повышения исключения в python - PullRequest
0 голосов
/ 04 мая 2020

У меня есть следующий код:

class A:
    def __del__(self):
        print('del A')


class B:
    def foo(self):
        a = A()
        raise RuntimeError


b = B()
try:
    b.foo()
    print('after b.foo() 1')
except RuntimeError:
    print('catch error')

print('after b.foo() 2')

Вывод:

catch error
del A
after b.foo() 2

Мои вопросы:

1) Кажется, что a удаляется после обработки исключений. Может ли кто-нибудь помочь объяснить порядок выпуска переменной в таких случаях?

2) Как вручную освободить переменную a в начале блока except RuntimeError?

Еще несколько слов о случае использования:

Я хотел бы перехватить CUDA из-за ошибки памяти, возникшей в B.foo(), и освободить некоторые a (некоторые переменные, занимающие слишком много памяти CUDA) в начале блока except RuntimeError , Затем я могу разделить данные на более мелкие части и сделать это снова.

Ответы [ 2 ]

0 голосов
/ 04 мая 2020

Я думаю, я нашел решение. [traceback.clear_frames] (https://docs.python.org/3/library/traceback.html#traceback .clear_frames ) делает волхвов c.

import sys
import traceback
class A:
    def __del__(self):
        print('del A')


class B:
    def foo(self):
        a = A()
        raise RuntimeError 


b = B()
try:
    b.foo()
    print('after b.foo() 1')
except RuntimeError:
    exc_type, exc_value, exc_traceback = sys.exc_info()
    traceback.clear_frames(exc_traceback)
    print('catch error')

print('after b.foo() 2')
0 голосов
/ 04 мая 2020

Сделайте a атрибутом вашего B экземпляра и удалите его:

class B:
    def foo(self, num):
        self.a = A()           # make it an attribute so you can access it from outside
        if num > 20:
            raise RuntimeError


b = B() 
try:
    b.foo(42)
    print('after b.foo() 1')
except RuntimeError:
    del b.a                    # now you can explicitly delete it
    print('catch error')
    b.foo(18)                 
    print('after b.foo() 1a')

print('after b.foo() 2')

Если, возможно, будет удобнее использовать test_memory(self, data) и повторять его до истины, затем продолжайте.

Не уверен, что вышеуказанный подход работает с CUDA.

...