Frage

Was ist das Verhalten von cx_Oracle Cursor, wenn das Verbindungsobjekt von verschiedenen Threads verwendet wird? Wie würden Generatoren beeinflussen dieses Verhalten? Insbesondere ...

Bearbeiten : Die ursprüngliche Beispiel Funktion war falsch; ein Generator, der durch eine Unterfunktion zurückgegeben wurde, wurde yield nicht direkt in der Schleife verwendet. Damit wird klar gestellt, wenn finally ausgeführt wird (nach return der Fall ist), aber nicht beantwortet immer noch nicht, ob ein Cursor verwendet werden kann, wenn ein anderer Thread das Verbindungsobjekt beginnt mit dem Cursor aus erstellt wurde. Es scheint tatsächlich (in Python 2.4, zumindest), try...finally mit yield verursacht einen Syntaxfehler.

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() ist eine Funktion von mehreren Threads aufgerufen. Die Verbindungen werden mit dem Argument threaded=False erstellt.

Ich frage mich ...

  1. Ist Gewinde 1 der cursor Objekt noch verwendbar, wenn Gewinde 2 kommen und verwenden das gleiche Verbindungsobjekt? Wenn nicht, was passieren könnte?

Das Verhalten i sehen bin eine Ausnahme in cx_Oracle spricht von einem Protokollfehler, und dann ein segfault folgt.

War es hilfreich?

Lösung

Siehe die docs : threadsafety ist, und ich zitiere:

  

Zur Zeit 2, was bedeutet, dass Fäden   kann das Modul und Verbindungen teilen,   aber nicht Cursor.

So Ihr „Pool von Cursor“ construct (wo ein Cursor durch verschiedene Threads verwendet werden kann) scheint über das threadsafety Niveau. Es ist nicht eine Frage des Teilens Verbindungen aber Cursor (das ist in Ordnung, da Sie threaded richtig in die Verbindung des Konstruktor übergeben haben). Sie können jeden Cursor in threading.local nach dem ersten Mal speichern möchten ein Thread es verwendet hat, so dass jeder Thread kann seine eigenen 1-Cursor „Pool“ (keine Schlüssel Optimierung haben, aber: einen neuen Cursor zu machen ist kein Schwer- Betriebsbelastu).

Wrt Ihre Frage 2, die finally Klausel ausgeführt wird, wenn der Generator Objekt (gebaut von einem Aufruf an Ihrer Generatorfunktion Get) ist alles erledigt - entweder weil es StopIteration erhöhen, oder weil es Müll gesammelt hat wird (in der Regel, weil die letzte Referenz um es einfach weg weg) hat. Z. B, wenn der Anrufer ist:

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'

die finally aus, nachdem (höchstens) 3 Reihen haben yielded worden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top