Ric*_*eur 5 python multithreading cx-oracle yield generator
当连接对象被不同线程使用时,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
Run Code Online (Sandbox Code Playgroud)
Get()是一个被多个线程调用的函数。连接是通过threaded=False参数创建的。
我在想...
cursor如果线程 2 出现并使用相同的连接对象,线程 1 的对象是否仍然可用?如果没有,可能会发生什么?我看到的行为是 cx_Oracle 中谈论协议错误的异常,然后出现段错误。
请参阅文档: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'
Run Code Online (Sandbox Code Playgroud)
finally(最多)3 行被编辑后执行yield。