我在 python 代码中通过 ODBC 连接连接到 DB2 服务器。 DB2 服务器为了维护而重新启动,或者在运行特定服务器端任务时断开连接,这种情况一天会发生 1 到 2 次。当时,如果我的代码开始执行 pandas read_sql 函数来获取查询结果,即使服务器在 1 小时后启动,它也会进入无限等待。
我想在 read_sql 的执行中设置超时,每当发生超时时,我想刷新与 DB2 服务器的连接,以便在继续查询之前再次建立新的连接。
我尝试过创建一个 while 循环并从 DB2 中选取数据块,而不是立即提取整个结果,但问题是如果 DB2 在提取块时断开连接,python 代码仍然会进入无限等待。
chunk_size = 1000
offset = 0
while True:
sql = "SELECT * FROM table_name limit %d offset %d" % (chunk_size,offset)
df = pd.read_sql(sql, conn)
df.index += (offset+1)
offset += chunk_size
sys.stdout.write('.')
sys.stdout.flush()
if df.shape[0] < chunk_size:
break
如果 sql 执行时间超过 3 分钟,我需要 read_sql 抛出一些异常或返回一个值。如果发生这种情况,我需要连接到 DB2 才能刷新。
您可以使用该套件
func-timeout
。您可以通过 pip 安装,如下所示:
pip install func-timeout
因此,例如,如果您有一个函数“doit('arg1', 'arg2')”,您希望限制其运行时间为 5 秒,则可以使用 func_timeout 来调用它:
from func_timeout import func_timeout, FunctionTimedOut
try:
doitReturnValue = func_timeout(5, doit, args=(‘arg1’, ‘arg2’))
except FunctionTimedOut:
print ( “doit(‘arg1’, ‘arg2’) could not complete within 5 seconds, hence terminated.\n”)
except Exception as e:
# Handle any exceptions that doit might raise here
理论上您可以在数据库后端设置读取超时。例如,如果您将 sqlalchemy 与
pymysql
一起使用,则应该是:
from sqlalchemy import create_engine
eng = create_engine("mysql+pymysql://username:password@host:port/database",
connect_args={'connect_timeout': 10.0, 'read_timeout': 180.0})
但是 read_timeout 在我的情况下不起作用。不确定这是否是 pymysql 的问题。如果您有不同的后端,请尝试查找连接器的文档并将相应的关键字 arg 传递给
connect_args
参数(也可能是 read_timeout
)