Какие типы аргументов встроены в Python __exit__? - PullRequest
2 голосов
/ 11 ноября 2019

Классы имеют определяемую функцию __exit__, которая позволяет реализацию диспетчера контекста.

Он принимает необходимые аргументы:

def __exit__(self, exc_type, exc_val, exc_tb):

, но я не могу найти окончательное определение того, что этиАргументы и их типы.

Вот мое лучшее предположение о том, что они и почему, но я не совсем уверен:

def __exit__(self, exc_type: Exception, exc_val: TracebackException, exc_tb: TracebackType):

exc_type

Python определяетTracebackException класс, который принимает аргумент exc_type, который используется контекстно в конструкторе в issubclass с SyntaxError, что означает, что exc_type действительно является своего рода Exception, что SyntaxError наследуется от.

exc_val

Кроме того, в этом TracebackException классе есть аргумент exc_value, который соответствует нашему exc_val, который, кажется, имеет различные атрибуты, такие как __cause____context__ и другие атрибуты, которые определены в самом TracebackType. Это заставляет меня думать, что сам параметр является экземпляром TracebackException.

exc_tb

Python определяет функцию walk_tb , которая использует exc_tb в качестве аргумента (вручнуютрассируется из docs.python.org ), и этот объект, похоже, имеет атрибуты tb_frame, tb_lineno и tb_next, которые можно проследить до класса TracebackType в typeshed библиотека.

Мысли?

1 Ответ

3 голосов
/ 11 ноября 2019

exc_type - класс исключения. exc_val является экземпляром исключения. exc_tb является объектом трассировки, ссылка на который есть в types.TraceBackType.

Как правило,

  • type(exc_val) is exc_type
  • exc_val.__traceback__ is exc_tb

Обратите внимание, что __exit__ по-прежнему вызывается, когда не было исключений, вызванных кодом из диспетчера контекста, и аргументы будут (None, None, None), поэтому все три аргумента должны быть аннотированы необязательно .

Тогда правильная аннотация для него должна выглядеть примерно так:

def __exit__(self, exctype: Optional[Type[BaseException]],
             excinst: Optional[BaseException],
             exctb: Optional[TracebackType]) -> bool: ...

Вас может удивить, почему у этого API есть три аргумента, когда два из них могут бытьтривиально определяется из самого экземпляра исключения. Но так было не всегда: в старых версиях Python вы могли вызывать строки как исключения, а атрибут __traceback__ исключения отсутствовал до Python 2.5 . И вы все равно можете создавать классы старого стиля как исключения в Python 2.7 (!)

...