当连接对象被不同的线程使用时,cx_Oracle游标的行为是什么?发电机如何影响这种行为?具体地说...
修改:原始示例功能不正确;子函数返回了一个生成器,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
参数创建连接。
我想知道......
cursor
对象是否仍然可用?如果没有,会发生什么?我所看到的行为是cx_Oracle中的一个例外,它讨论了一个协议错误,然后是一个段错误。
答案 0 :(得分:2)
请参阅the docs:threadsafety
是,我引用,
目前2,表示线程 可以共享模块和连接, 但不是游标。
所以你的“游标池”构造(其中一个游标可能由不同的线程使用)似乎超出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
之后执行。