Pregunta

¿Cuál es el comportamiento de los cursores cx_Oracle cuando el objeto de conexión es utilizado por diferentes hilos? ¿Cómo afectará a los generadores de este comportamiento? Específicamente ...

Editar : La función original ejemplo era incorrecta; un generador estaba siendo devuelto por una función sub, yield no se utilizó directamente en el bucle. Esto clarifica cuando se ejecuta finally (después de return hace), pero todavía no responde si un cursor se puede utilizar si otro hilo comienza a utilizar el objeto de conexión el cursor se creó a partir. En realidad, parece (en Python 2.4, por lo menos), try...finally con yield provoca un error de sintaxis.

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() es una función llamada por múltiples hilos. Las conexiones se crean con el argumento threaded=False.

Me pregunto ...

  1. ¿Es el hilo de 1 objeto cursor usables si rosca 2 llega y utiliza el mismo objeto de conexión? Si no es así, lo que podría suceder?

El comportamiento que estoy viendo es una excepción en cx_Oracle hablando de un error de protocolo, y luego una violación de segmento siguiente.

¿Fue útil?

Solución

los documentos : threadsafety es, y cito,

  

Actualmente 2, lo que significa que los hilos   pueden compartir el módulo y conexiones,   pero no los cursores.

Por lo que su construcción "pool de cursores" (donde un cursor puede ser utilizado por diferentes hilos) parece estar más allá del nivel threadsafety. No es una cuestión de compartir conexiones (eso está bien ya que he pasado threaded adecuadamente en el constructor de la conexión), pero los cursores. Es posible que desee almacenar cada cursor en threading.local después de la primera vez que un mensaje ha utilizado, de manera que cada hilo puede tener su propio 1-cursor del "pool" (no una optimización clave, sin embargo: hacer un nuevo cursor no es un pesado operación de trabajo).

Wrt pregunta 2, se ejecuta la cláusula finally cuando el objeto generador (construido por una llamada a la función Get generador) se hace todo - ya sea porque es elevar StopIteration, o porque está siendo recogido de basura (por lo general debido a que la última referencia a ella simplemente ha desaparecido). Por ejemplo, si la persona que llama es:

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'

se ejecuta el finally después (como máximo) 3 filas han sido yielded.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top