Odoo报错“Unable to use a closed cursor”:异步执行函数问题求助
解决Odoo中HTTP响应后线程调用函数出现“Unable to use a closed cursor”的问题
问题原因
当HTTP控制器返回响应后,Odoo会自动关闭当前请求绑定的数据库游标(request.env.cr)。你启动线程时复用了这个游标创建环境,线程执行时游标已经被系统关闭,因此触发“Unable to use a closed cursor”错误。
解决方案
核心思路是在线程内部创建独立的数据库连接和环境,不要复用请求上下文的游标。具体操作:
- 在线程函数中,通过
odoo.sql_db.db_connect创建新的数据库连接 - 基于新连接生成游标,再构建独立的Environment实例
- 线程执行完毕后,手动处理事务的提交/回滚,并关闭游标,避免资源泄漏
修改后的代码示例
import threading import odoo from odoo import http, api class SomeAPIEndpoint(http.Controller): @http.route('/api', type='json') def controller(self, **kwargs): data = self.function1(request) # 传递线程所需的基础参数,避免直接传递请求上下文对象 t = threading.Thread(target=self.function2, args=(request.env.cr.dbname, request.env.user.id, request.env.context)) t.start() return data def function1(self, request): # 处理请求并返回响应数据 data = request.env['some.model'].search([]) # 数据处理逻辑... return data def function2(self, dbname, user_id, context): # 创建独立的数据库连接与游标 with odoo.sql_db.db_connect(dbname).cursor() as cr: with api.Environment.manage(): env = api.Environment(cr, user_id, context) try: # 执行cron触发逻辑 cron = env['ir.cron'].search([('id', '=', 1)]) cron.with_user(cron.user_id).with_context(lastcall=cron.lastcall).ir_actions_server_id.run() # 提交事务(若涉及数据修改) cr.commit() except Exception as e: # 异常时回滚事务 cr.rollback() # 可添加日志记录逻辑 raise e
关键说明
- 线程启动时仅传递数据库名、用户ID和上下文,避免直接传递请求相关的游标或环境对象
- 在线程内部通过
db_connect创建独立连接,确保游标不受请求生命周期影响 - 使用
with语句管理游标和环境,自动释放资源;手动处理事务提交/回滚,保证数据一致性
内容的提问来源于stack exchange,提问作者Pypax
相关产品推荐
相关产品推荐

