【问题标题】:Stop Python throwing errors when SQL statement returns no rows当 SQL 语句不返回任何行时,停止 Python 抛出错误
【发布时间】:2020-01-14 09:47:34
【问题描述】:

我一直在使用 python 自动执行一些 SQL 查询,并且我一直在尝试使用 try 和 except 来捕获错误。这在大多数情况下都可以正常工作,但如果我的 SQL 语句不返回行(例如,插入到数据库中的表中),那么它会发送错误并停止脚本。

错误看起来像:

此结果对象不返回行。它已自动关闭。

有没有办法使用 case 语句或类似的语句,如果错误与上述相同,则继续运行,否则停止?

示例代码:

import time
import logging   
import datetime
import sys
from datetime import timedelta

def error_logs(e):
    #calculate running time
    runtime = (time.time() - start_time)

    #capture error messages (only using Line number)
    exc_type, exc_obj, exc_tb = sys.exc_info()
    #fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
    line =  'Line ' + str(exc_tb.tb_lineno)   

    #print the error 
    logging.exception("Error")
    message = "***ERROR***: Script Failed. "
    write_logs((str(datetime.datetime.now()) + ", " + message + str(e) + ". " + line + ". Run time: " + str(round(runtime)) + " seconds." + "\n"))

def write_logs(message):
    log_path = r"C:\Logs\Logs.txt"
    with open(log_path, 'a+') as log:        
        log.write(str(datetime.datetime.now()) + ", " + message + "\n")

try:
    db.query(''' 
    insert into my_table (column1, column2, column3)
    select * from my_other_table
    where date = '2019-09-12'
    ''')

except Exception as e:    
    error_logs(e)

【问题讨论】:

  • 这是一个引发的异常吗? 记录的消息?你在用什么图书馆?那不是有效的 Python……
  • 所以db.query 引发空结果异常?我会从那里开始,这似乎是不寻常的行为。 db 是什么?你自己的课?一些现有的数据库适配器? – 如果无法修复该行为,那么它会引发什么类型的错误?一些不同的类型,还是通用的?
  • 无论 db 是什么,它都可以区分查询(可以返回行)和不能使用的“插入”语句。所以“db.query”可能只是错误的方法。
  • 然后删除 try/excet 以查看完整的错误消息
  • 如果db.query() 是你自己的函数,那么检查这个函数是否需要行,也许你应该添加一些if/else 来解决这个问题

标签: python sql error-handling try-catch


【解决方案1】:

查看此答案的第一部分:https://stackoverflow.com/a/14388356/77156

第一个答案 - 关于“防止自动关闭”。

SQLAlchemy 使用 insert 和 do 运行 DBAPI execute() 或 executemany() 不做任何选择查询。所以你得到的例外是预期的 行为。执行插入查询后返回的 ResultProxy 对象 包装不允许对其执行 .fetchall() 的 DB-API 游标。一次 .fetchall() 失败,ResultProxy 将您看到的异常返回给用户。

插入/更新/删除操作后您可以获得的唯一信息 将是受影响的行数或之后的主键值 自动递增(取决于数据库和数据库驱动程序)。

如果您的目标是接收此类信息,请考虑检查 ResultProxy 方法和属性,如:

.inserted_primary_key
.last_inserted_params()
.lastrowid
etc

【讨论】:

  • 是的,我在 SQLAlchemy 的 result.py 文件中找到了这部分代码: def _non_result(self, default): if self._metadata is None: raise exc.ResourceClosedError("这个结果对象不返回行. " "已自动关闭。", ) elif self.closed: raise exc.ResourceClosedError("此结果对象已关闭。") else: return default
【解决方案2】:

我找到了解决我自己问题的方法。您可以通过在末尾添加一个虚拟 select 语句来强制 SQL 返回一些数据行。这样它就不会认为结果为空,从而不会抛出错误。

db.query(''' 
    insert into my_table (column1, column2, column3)
    select * from my_other_table
    where date = '2019-09-12';
    select 'test';
    ''')

问题源于 SQL Alchemy 的代码在 sql 语句的结果中搜索一些元数据(并且没有任何用于插入语句的元数据)。

来自 SQLAlchemy 包中的 result.py

def _non_result(self, default):
        if self._metadata is None:
            raise exc.ResourceClosedError(
                "This result object does not return rows. "
                "It has been closed automatically.",
            )
        elif self.closed:
            raise exc.ResourceClosedError("This result object is closed.")
        else:
            return default

【讨论】:

  • 你会认为有一些方法可以在不引发 SQLAlchemy 错误的情况下进行 INSERT 查询......??‍♂️
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-15
  • 1970-01-01
  • 2022-01-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多