Вопрос

Каково поведение курсоров cx_Oracle, когда объект connection используется разными потоками?Как генераторы повлияют на это поведение?В частности...

Редактировать:Исходный пример функции был некорректным;генератор возвращался подфункцией, yield не использовался непосредственно в цикле.Это проясняет , когда finally выполняется (после return делает), но по-прежнему не отвечает, можно ли использовать курсор, если другой поток начнет использовать объект подключения, из которого был создан курсор.Это действительно кажется (по крайней мере, в python 2.4), try...finally с yield вызывает синтаксическую ошибку.

def Get()
  conn = pool.get()
  try:
    cursor = conn.cursor()
    cursor.execute("select * from table ...")
    return IterRows(cursor)
  finally:
    pool.put(conn)

def IterRows(cursor):
  for r in cursor:
    yield r

Get() это функция, вызываемая несколькими потоками.Соединения создаются с помощью threaded=False аргумент.

Мне интересно...

  1. Является потоком 1 cursor объект все еще можно использовать, если появится поток 2 и использует тот же объект подключения?Если нет, то что может произойти?

Поведение, которое я вижу, - это исключение в cx_Oracle, говорящее об ошибке протокола, а затем следует segfault .

Это было полезно?

Решение

Видишь документы: threadsafety есть, и я цитирую,

В настоящее время 2, что означает, что потоки могут совместно использовать модуль и соединения, но не курсоры.

Таким образом, ваша конструкция "пула курсоров" (где один курсор может использоваться разными потоками), похоже, выходит за рамки threadsafety Уровень.Это не проблема совместного использования подключений (это нормально, поскольку вы прошли threaded правильно в конструкторе соединения), но курсоры.Возможно, вы захотите сохранить каждый курсор в threading.local после того, как поток использовал его в первый раз, так что каждый поток может иметь свой собственный "пул" с одним курсором (хотя это и не ключевая оптимизация:создание нового курсора не является трудоемкой операцией).

Wrt ваш вопрос 2, the finally предложение выполняется, когда объект генератора (созданный вызовом вашей функции генератора Get) все сделано - либо потому, что это повышает StopIteration, или потому, что он собирается как мусор (обычно потому, что последняя ссылка на него только что исчезла).Например, если вызывающий абонент является:

def imthecaller():
  for i, row in enumerate(Get()):
    print i, row
    if i > 1: break
  # this is the moment the generators' finally-clause runs
  print 'bye'

в finally выполняется после того, как (не более) 3 строки были yieldэд.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top