Pandas read_sql() 可以返回哪些异常

Posted

技术标签:

【中文标题】Pandas read_sql() 可以返回哪些异常【英文标题】:What exceptions could be returned from Pandas read_sql() 【发布时间】:2017-07-16 21:41:13 【问题描述】:

我有一个用户定义的函数,它使用 pymysql 连接到 mysql 数据库,然后它询问数据库并将结果读入 Pandas 数据框。

import pandas as pd
import pymysql
import getpass

def myGetData(myQuery):

    myServer = 'xxx.xxx.xxx.xxx'
    myUser = input("Enter MySQL database username: ")
    myPwd = getpass.getpass("Enter password: ")

    myConnection = pymysql.connect(host=myServer,user=myUser,password=myPwd)

    myTempDF = pd.io.sql.read_sql(myQuery, con=myConnection)

    myConnection.close()

    return myTempDF

myDF = myGetData("SELECT * FROM `myDB`.`myTable`")

我已经编写了代码来捕获由 pymysql.connect() 引起的异常,尽管为了清楚起见我没有在这里展示它。我还希望能够捕获可能由 read_sql() 引起的任何异常。在哪里可以找到可能引发的异常列表?它不在 Pandas 文档 (http://pandas.pydata.org/pandas-docs/version/0.19.2/generated/pandas.read_sql.html) 中,我在网上找不到任何提示。我可以捕获所有异常,但这似乎被 Python 社区普遍反对。我应该如何捕获 read_sql() 引发的异常?

编辑

我在这方面做了更多的工作,似乎即使我知道正在生成什么错误,捕捉异常也不是直截了当的。因此,例如,在上面给出的代码中,如果我输入的用户名和/或密码不正确,就会产生操作错误。最后一行或错误报告的内容如下:

OperationalError: (1045, "Access denied for user 'yyy'@'xxx.xxx.xxx.xxx' (using password: YES)")

我已经能够使用以下方法捕获此错误:

try:
    phjConnection = pymysql.connect(host=phjServer, user=phjUser, password=phjPwd)

except pymysql.OperationalError as e:
            print("\nAn OperationalError occurred. Error number 0: 1.".format(e.args[0],e.args[1]))

这很好用(尽管发现 OperationalError 需要使用 pymysql.OperationalError 来捕获是偶然的)。

现在,在函数的下一部分,Pandas 函数 real_sql() 使用上面创建的连接来运行 SQL 查询。如果我包含一个故意不正确的查询,该查询具有不正确的表名,则会发生另一个 OperationalError,然后是 DatabaseError:

OperationalError: (1142, "SELECT command denied to user 'yyy'@'xxx.xxx.xxx.xxx' for table 'table'")

During handling of the above exception, another exception occurred:

DatabaseError: Execution failed on sql 'SELECT * FROM `db`.`table`': (1142, "SELECT command denied to user 'yyy'@'xxx.xxx.xxx.xxx' for table 'table'")

但我现在完全不知道如何捕获第二个 OperationalError。之前使用的 pymysql.OperationalError 不起作用。我已经尝试了几乎所有我能想到的东西,但仍然无法捕捉到错误。错误消息不应该更多地说明错误是如何生成的以及如何捕获它吗?显然,我遗漏了一些明显的东西,但我找不到解决方案。任何建议将不胜感激。

编辑 2

作为对评论的回应,我现在捕获的异常如下:

import pandas as pd
import pymysql
import getpass

def myGetData(myQuery):

    myServer = 'xxx.xxx.xxx.xxx'
    myUser = input("Enter MySQL database username: ")
    myPwd = getpass.getpass("Enter password: ")

    try:
        myConnection = pymysql.connect(host=myServer,user=myUser,password=myPwd)

    except pymysql.OperationalError as e:
        # Catching this exception works fine if, for example,
        # I enter the wrong username and password
        print("\nAn OperationalError occurred. Error number 0: 1.".format(e.args[0],e.args[1]))

    try:
        myTempDF = pd.io.sql.read_sql(myQuery, con=myConnection)

    except pymysql.OperationalError as e:
        # However, this error isn't picked up following an incorrect
        # SQL query despite the error message saying that an
        # OperationalError has occurred.
        # Many variations on this theme have been tried but failed.
        print("\nAn error occurred. Error number 0: 1.".format(e.args[0],e.args[1]))

    myConnection.close()

    return myTempDF

myDF = myGetData("SELECT * FROM `myDB`.`myTable`")

【问题讨论】:

您可以编辑代码以显示您现在如何处理错误吗? 添加了第二个编辑,以显示现在如何尝试捕获错误。 【参考方案1】:

好问题,注意,read_sql 是 'read_sql_table 和 read_sql_query 的包装器。通读source,ValueError 始终被抛出到父函数和辅助函数中。所以你可以安全地抓住ValueError 并妥善处理。 (请看源码)

【讨论】:

感谢您的建议...我去看看。 这是一个很好的提示 (++)。 @user1718097,您可能还想检查相应源文件中的 SQLAlchemy 异常(因为 Pandas 在 to_sql() 中使用此模块)... 我在这个问题上做了更多的工作,并在原始问题中添加了一个编辑。【参考方案2】:

我只是在一个类似的问题中偶然发现了这个问题,并找到了从 SQLalchemy 中寻求异常的答案。

try:
        df = pd.read_sql_query(QUERY, engine)
    except sqlalchemy.exc.OperationalError as e:
        logger.Info('Error occured while executing a query '.format(e.args))

更多信息可以在这里找到。 SQL Alchemy Docs

【讨论】:

只是我需要的信息,我将 Operational 切换到 Programming 以进行 SQL 语法检查。 注意: 您也可以将诸如 execpt (sqlaclchemy.exc.ProgrammingError, sqlalchemy.exc.OperationalError) as e: 之类的 except 语句串起来以全部捕获

以上是关于Pandas read_sql() 可以返回哪些异常的主要内容,如果未能解决你的问题,请参考以下文章

pandas read_sql 没有读取所有行

Python pandas read_sql 返回生成器对象

Pandas read_sql 列不正确

如何使 pandas.read_sql() 不将所有标题转换为小写

pd.read_sql字符类型

使用 pandas.read_sql 和 MSAccess 的特定表名的“sql 执行失败”