2017-02-26 60 views
4

我有一個用戶定義的函數,它使用pymysql連接到mysql數據庫,然後它詢問數據庫並將結果讀入熊​​貓數據框。熊貓可以返回什麼異常read_sql()

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()中可能出現的任何異常。我在哪裏可以找到可能會引發異常的列表?它不在熊貓文檔(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不起作用。我嘗試了幾乎所有我能想到的事情,但仍然無法捕捉到錯誤。不應該錯誤信息是關於如何產生錯誤以及如何捕獲錯誤信息?顯然,我錯過了一些明顯的東西,但我找不到解決方案。任何建議,將不勝感激。

EDIT 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`") 
+0

你能編輯代碼來顯示你現在如何處理錯誤嗎? – putonspectacles

+0

添加了第二個編輯,以顯示現在如何嘗試捕獲錯誤。 – user1718097

回答

2

好問題,注意,read_sql是圍繞「read_sql_table和read_sql_query的包裝。通過source閱讀,ValueError始終引發父和輔助函數。因此,您可以安全地抓住ValueError並妥善處理。 (看看源代碼)

+0

感謝您的建議...我會看看。 – user1718097

+0

這是一個很好的提示(++)。 @ user1718097,你可能也想檢查SQLAlchemy的異常(因爲Pandas在'to_sql()')的相應源文件中使用了這個模塊... – MaxU

+0

我在這個問題上做了更多的工作,並且添加了一個EDIT原來的問題。 – user1718097