Как завершаются контекстные менеджеры в неиспользованных генераторах?

Это короткий метод C #, который работает для меня. Int32 достаточно большой для моих целей.

public static Int32 GetNextID( SqliteConnection AConnection )
{
  Int32 result = -1;

  using ( SqliteCommand cmd = AConnection.CreateCommand() )
  {
    cmd.CommandText = "SELECT last_insert_rowid();";
    using ( SqliteDataReader r = cmd.ExecuteReader() )
    {
      if ( r.Read() )
        result = (Int32) r.GetInt64( 0 );
    }
  }

  return result;
}
5
задан jdehesa 17 January 2019 в 16:48
поделиться

1 ответ

Примите во внимание следующее:

@contextmanager
def ctx():
    print('enter ctx')
    try:
        print('ctx begins yield')
        yield
        print('ctx finishes yield')
    finally:    
        print('exit ctx')

def gen_nums(n):
    print('entering generator')
    l = range(n)
    with ctx():
        print('inside context manager')
        for i in l:
            print('gen before yield')
            yield i
            print('gen after yield')
        print('existing ctx')
    print('exiting generator')

Результат таков: ] последней итерации generator и до того, как она достигнет StopIteration. Таким образом, на самой последней итерации generator contextmanager оставался бы открытым, если бы он не выполнялся в цикле for (который обрабатывает StopIteration).

Вы не сможете поймать StopIteration в contextmanager, потому что это происходит после , когда generator исчерпан, и в этот момент contextmanager уже был бы завершен ,

Кроме того, IIRC, при построении contextmanager вы всегда должны использовать try... finally... в любом случае.

0
ответ дан Idlehands 17 January 2019 в 16:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: