如何捕获特定于包的异常?

How to catch a package-specific exception?

提问人:marianoju 提问时间:10/24/2023 最后编辑:marianoju 更新时间:10/25/2023 访问量:53

问:

当我尝试使用 pandas 从 SQL 数据库中读取表时,包 pyodbc 抛出一个 (pyodbc.DataError),我想抓住。这是由意外的 nvarchar 值引起的,当 pyodbc 尝试将其转换为数据类型 int 时,会导致转换失败。pandas.read_sqlDataErrorDataError

这是我的代码:

import pandas as pd 
import pyodbc
from sqlalchemy import create_engine
from sqlalchemy.engine import URL

driver = "SQL Server"
server = "my_server" 
database = "my_db" 

connection_string = (f"Driver={driver};"
                     f"Server={server};"
                     f"Database={database};"
                     f"Trusted_Connection=yes;"
                     f"TrustServerCertificate=yes")

connection_url = URL.create("mssql+pyodbc", 
                            query={"odbc_connect": connection_string})

engine = create_engine(connection_url)

# select only the first 10 rows in a table 
query = (f"SELECT top 10 * "
         f"FROM abc.table_name")

df = pd.read_sql(sql=query, 
             con=engine)

输出为

DataError: (pyodbc.DataError) ('22018', "[22018] [Microsoft][ODBC SQL Server Driver][SQL Server]Conversion failed when converting the nvarchar value '00:35' to data type int. (245) (SQLExecDirectW)")
[SQL: SELECT top 10 * FROM abc.table_name]
(Background on this error at: https://sqlalche.me/e/14/9h9h)

我知道如何使用 Python 中的 and 语句捕获和处理内置异常。(pyodbc.但是,DataError) 不是内置异常。我想捕获此特定于软件包的错误,而不仅仅是捕获任何错误(我知道这是不好的做法)。tryexceptDataError

我尝试了以下方法:

try: 
    df = pd.read_sql(sql=query, 
                 con=engine)
except DataError as err: 
    print(err)
    pass

这会导致(据我了解,因为不是内置异常)。NameError: name 'DataError' is not definedDataError

我还尝试了以下方法:

try: 
    df = pd.read_sql(sql=query, 
                 con=engine)
except pyodbc.DataError as err: 
    print(err)
    pass

这会导致 ,因为未捕获错误。DataError: (pyodbc.DataError)

Python pandas 异常 pyodbc

评论

2赞 Abdul Niyas P M 10/24/2023
最后一个片段抓住了异常,对吧?
1赞 Waket Zheng 10/24/2023
你可以获取它的类名print(type(err))
0赞 marianoju 10/25/2023
@AbdulNiyasPM 最后一个代码段未捕获异常,因为类名不正确。
0赞 marianoju 10/25/2023
@WaketZheng 是的,谢谢!我没有想到这一点。

答:

3赞 Learning is a mess 10/24/2023 #1

DataError似乎是SQLalchemy的例外,请参阅文档:https://docs.sqlalchemy.org/en/20/core/exceptions.html#sqlalchemy.exc.DataError

尝试:

from sqlalchemy.exc import DataError

然后

try:
    df = pd.read_sql(sql=query, 
                 con=engine)
except DataError as err: 
    print(err)
    pass

评论

0赞 STerliakov 10/25/2023
并被打印出来,因为 sqlalchemy 的 DataError 是从中重新引发的,并传播了消息。pyodbc.DataError
1赞 marianoju 10/25/2023
正如 @WhaketZheng 所评论的那样,允许获取异常的正确类名:。print(type(err))<class 'sqlalchemy.exc.DataError'>
1赞 Waket Zheng 10/24/2023 #2

可以通过以下方式获取异常的类名:

try: 
    df = pd.read_sql(sql=query, 
                 con=engine)
except Exception as e: 
    print(type(e))
    raise e

有时你可能需要使用 BaseException 来捕获一些特殊的异常(例如 SystemExit/KeyboardInterrupt)

try:
    do_stuff()
except BaseException as e:
    print(type(e), e)
    raise e

评论

0赞 STerliakov 10/25/2023
或者,如果可以附加到调试器会话,则无需打印,以便有机会实时调查此问题。breakpoint()