天天看點

關于Python連接配接資料庫的三種方式最後問題的解答

作者:hxliu666

問題複現

在上一篇文章Python連接配接資料庫的三種方式中,遺留了一個問題,就是通過jar包的方式連接配接資料庫時,如果我們使用的是多資料源的話,我們應該怎麼處理呢?現在我把整個過程梳理一下(>>> jaydebeapi.__version__;'1.2.3'):

  • 通過前文,大家清楚了通過jar包是如何連接配接資料庫的,其實和通過JDBC進行連接配接的配置是一樣。大緻所需内容如下:
jaydebeapi.connect(jclassname=driver, url=url, driver_args=[user, password], jars=jarFile)
//簡單來講,和Java裡面配置資料庫所需要的連接配接資訊一緻。           
  • 那麼如果是連接配接連接配接兩個資料源且不同種類的庫呢?正常來講,我們會通過如下的方式來寫(source_conn 和 des_conn……):
source_conn = jaydebeapi.connect(jclassname=source_driver, url=source_url, driver_args=[source_user, source_password], jars=source_jarFile)
des_conn = jaydebeapi.connect(jclassname=des_driver, url=des_url, driver_args=[des_user, des_password], jars=des_jarFile)           

錯誤原因分析:

在寫完之後,本以為可以正常運作達到自己預期的時候,結果報錯了?報錯資訊如下:

jpype._jclass.NoClassDefFoundError: java.lang.NoClassDefFoundError: oracle/jdbc/driver/OracleDriver
//這裡面報錯資訊很直接明了。NoClass           

從上面的錯誤代碼中,我們很清楚地看到,明明參數都配置了,傳參也指定了,為什麼呢?通過報錯資訊,我簡單地閱讀了一下源碼。我的了解如下:

關于Python連接配接資料庫的三種方式最後問題的解答

完整的報錯資訊

從完整的報錯資訊,我們可以看到關聯到的幾個檔案。先看“__init__.py”檔案,部分代碼如下:

關于Python連接配接資料庫的三種方式最後問題的解答

報錯資訊412行相關資訊

從上圖中,可以清楚地看到。這部分主要在處理參數,最後去調用函數“_jdbc_connect”,接下來我們繼續去看報錯資訊中提示的報錯行數221,相關内容如下:

關于Python連接配接資料庫的三種方式最後問題的解答

報錯資訊221相關内容

從上圖中,可以看到,報錯的地方是在“jpype.JClass(jclassname)”,那麼它為什麼會報錯呢?請大家看我劃的左側紅線,說明報錯的地方和藍色的框是同一層級的。藍色的地方要執行的前期是“if not jpype.isJVMStarted():”,而我們在執行第一個“source_conn”時,相關的參數資訊已經傳入并且已經連接配接成功了,說明它已經不符合jvm不啟動的分支,是以不會進入相關的流程,隻有進入相關的流程才會處理jars等相關參數。是以 在執第二個“des_conn”時,“jpype.JClass(jclassname)”,參數jars還是原來的值,jclassname和jars對應關系不存在而發生的錯誤,簡單來講就是找不到對應的jar包而導緻的報錯。

如果大家仔細看的話,在分析錯誤資訊的時候,其實有個小小的漏洞,就是我們在412行看到“_jdbc_connect“,為什麼到了212行時,發現函數盡然是”_jdbc_connect_jpype“,為什麼呢?原因如下:

關于Python連接配接資料庫的三種方式最後問題的解答

解決方法:

通過上面的分析,我們初步可以确定出現問題的原因,那麼我們該如何解決此問題呢?從上面可以看到它隻加載一次,那麼我們讓它一次加載所有jar包進去就可以了。解決方法如下:

  • 一次性寫到檔案中格式如下:
jarfile=['./ojdbc6-11.2.0.3.jar','./mysql-connector-java-8.0.22.jar']           
  • 從配置檔案中擷取

配置檔案格式如下:

jarFile = ./ojdbc6-11.2.0.3.jar,./mysql-connector-java-8.0.22.jar
           

Python檔案中可以通過子產品configparser來擷取并進行轉化

jarFile = config_raw.get("GLOBAL","jarFile")
jarFile = jarFile.split(",")            

下面是驗證一些想法的操作,供大家參考。

關于Python連接配接資料庫的三種方式最後問題的解答

我修改了源檔案,添加了相應的輸出,以此來驗證自己的想法是否正确。

下面分别是正确和報錯的兩次輸出結果如下:

關于Python連接配接資料庫的三種方式最後問題的解答

正确輸出

關于Python連接配接資料庫的三種方式最後問題的解答

錯誤輸出

通過上面的對比,可以看到它就加載了一次jar包。上面是我對此問題的一些了解。謝謝!