5

接続オブジェクトが異なるスレッドで使用されている場合、cx_Oracle カーソルはどのように動作しますか? ジェネレーターはこの動作にどのように影響しますか? 具体的には...

編集:元のサンプル関数は正しくありませんでした。サブ関数によってジェネレーターが返されましたyieldが、ループ内で直接使用されていませんでした。finallyこれにより、いつ実行されるか(実行後) が明確にreturnなりますが、別のスレッドがカーソルの作成元の接続オブジェクトの使用を開始した場合にカーソルを使用できるかどうかはまだわかりません。実際には (少なくとも python 2.4 では)、構文エラーが発生するようですtry...finallyyield

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. スレッド 2 が現れて同じ接続オブジェクトを使用する場合、スレッド 1 のcursorオブジェクトは引き続き使用できますか? そうでない場合、何が起こる可能性がありますか?

私が見ている動作は、プロトコル エラーについて話している cx_Oracle の例外であり、その後に segfault が続きます。

4

1 に答える 1

2

ドキュメントを参照してください:threadsafetyis、そして私は引用します、

現在2です。これは、スレッドがモジュールと接続を共有できるが、カーソルは共有できないことを意味します。

したがって、「カーソルのプール」構造(1つのカーソルが異なるスレッドで使用される可能性がある)は、threadsafetyレベルを超えているように見えます。これは、接続の共有の問題ではなく(threaded接続のコンストラクターを適切に渡したので問題ありません)、カーソルの問題です。スレッドが最初にカーソルを使用した後に各カーソルを格納しthreading.localて、各スレッドが独自の1カーソル「プール」を持つことができるようにすることができます(ただし、キーの最適化ではありません。新しいカーソルを作成することは強力ではありません。手術)。

質問2の場合、この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編集された後に実行されます。

于 2010-02-22T06:47:50.833 に答える