Rainbow Engine

IT技術を分かりやすく簡潔にまとめることによる学習の効率化、また日常の気付きを記録に残すことを目指します。

Python

PythonのSQLAlchemyで「ArgumentError : Could not parse rfc1738 URL」エラーや「InvalidRequestError: Could not reflect: requested tables(s)」エラーが出た時の対処について

投稿日:2020年3月15日 更新日:

(0)目次&概説

(1) エラー対応1:sqlalchemy.exc.ArgumentError
 (1-1) 発生状況・エラーメッセージ
  (1-1-1) エラーメッセージ
  (1-1-2) エラーとなったソース
 (1-2) 原因
 (1-3) 対処方法
(2) エラー2:Could not reflect: requested table(s)
 (2-1) 発生状況・エラーメッセージ
  (2-1-1) エラーメッセージ
  (2-1-2) エラーとなったソース
 (2-2) 原因
 (2-3) 対処方法

(1) エラー対応1:sqlalchemy.exc.ArgumentError

(1-1) 発生状況・エラーメッセージ

Web上で公開されているcsvデータのURLに対して「requests」パッケージの「get」関数を用いてデータを取得し、それをPandasの「read_csv」関数でDataframeに入れてから「to_sql」関数でOracleDBのテーブルにINSERTしようとした際にこのエラーに遭遇しました。

(1-1-1) エラーメッセージ
sqlalchemy.exc.ArgumentError: Could not parse rfc1738 URL from string '[Table name]'

 

(1-1-2) エラーとなったソース
import datapackage
import cx_Oracle
import sqlalchemy
import pandas as pd
import requests
from io import StringIO

def main():
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.76 Safari/537.36'}
    url = 'https://[your URL].json'
    dp = datapackage.Package(url)
    res = dp.resources

    from sqlalchemy import create_engine
    engine = create_engine('oracle://[your schema]:[your password]@[hostname]:[port]/[sid]')
    for res in res:
        if res.tabular:
            if res.descriptor['datahub']['type'] == 'derived/csv':
                s=requests.get(res.descriptor['path'], headers= headers).text
                df = pd.read_csv(StringIO(s))
                print(res.descriptor['path'])
                df.to_sql(engine,'CMTB_COMPANY_MASTER',if_exists='replace',index=False)

if __name__ == '__main__':
    main()

(図101)

目次にもどる

(1-2) 原因

引数の順番が正しく指定されていなかったためでした。「to_sql」関数は暗黙の「self」を除いた場合の第1引数は「SQLのテーブル名」で第2引数が”create_engine”関数の実行結果(sqlalchemy.engine.base.Engine)ですが、上記の例ではこれが逆になっているためにエラーとなっています。
(※本来はEngineインスタンス(「Engine(oracle://[your schema]:***@[hostname]:[port]/orcl)」のような文字列)を想定していた所、テーブル名を誤って引数として与えたため)

参考:Pandasの「to_sql」の説明
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to_sql.html

目次にもどる

(1-3) 対処方法

上記の第1引数”engine”と第2引数の”CMTB_COMPANY_MASTER”の順番を逆にしたら、当該エラーは起こらなくなりました。
(ただし、今度は後述の別のエラーに遭遇しますが・・)

df.to_sql('CMTB_COMPANY_MASTER',engine,if_exists='replace',index=False)

目次にもどる

(2) エラー2:Could not reflect: requested table(s)

(2-1) 発生状況・エラーメッセージ

(2-1-1) エラーメッセージ
sqlalchemy.exc.InvalidRequestError: Could not reflect: requested table(s) not available in Engine(oracle://[your schema]:***@[hostname]:[port]/orcl): ([your table name])

 

(2-1-2) エラーとなったソース

前の章からの主な差分箇所は以下です。
①SQLAlchemyの”create_engine”でEngineオブジェクトを作りDB接続しています。
②上記のEngineオブジェクトを用いてPandasの「to_sql」でDBのテーブルにレコードをINSERTしています。

import datapackage
import cx_Oracle
import sqlalchemy
import pandas as pd
import requests
from io import StringIO

def main():
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.76 Safari/537.36'}
    url = 'https://[your URL].json'
    dp = datapackage.Package(url)
    res = dp.resources

    from sqlalchemy import create_engine
    engine = create_engine('oracle://[your schema]:[password]@[hostname]:[port]/[sid]')
    for res in res:
        if res.tabular:
            if res.descriptor['datahub']['type'] == 'derived/csv':
                s=requests.get(res.descriptor['path'], headers= headers).text
                df = pd.read_csv(StringIO(s))
                print(res.descriptor['path'])
                df.to_sql('CMTB_COMPANY_MASTER',engine,if_exists='replace',index=False)

if __name__ == '__main__':
    main()

(図201)

目次にもどる

(2-2) 原因

「引数のテーブル名」と「DB側のテーブル名」がマッチしていない事が原因でした。どうやらDB側ではテーブル名を小文字に変換しているため、引数で大文字のテーブル名を与えると不一致でエラーとなるようです。実際に警告としてもその旨の文章が出ており「Consider using lower case table names」と小文字を推奨する記載も見受けられます。

C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python37_64\lib\site-packages\pandas\io\sql.py:1336: UserWarning: The provided table name 'CMTB_COMPANY_MASTER' is not found exactly as such in the database after writing the table, possibly due to case sensitivity issues. Consider using lower case table names.
  warnings.warn(msg, UserWarning)

目次にもどる

(2-3) 対処方法

テーブル名をstr型の変数に代入して「.lower()」メソッドで小文字変換することでミスマッチを防止できます。
■修正前:

df.to_sql('CMTB_COMPANY_MASTER',engine,if_exists='replace',index=False)

■修正後:

tab_name = 'CMTB_COMPANY_MASTER'
df.to_sql(tab_name.lower(),engine,if_exists='replace',index=False)

(図202)
・エラーは解消


・テーブルにも正常にレコードが格納されている

目次にもどる

Adsense審査用広告コード


Adsense審査用広告コード


-Python

執筆者:


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

関連記事

Slackでコマンドを作る方法をご紹介(自作スラッシュコマンド)

  <目次> (1) Slackでコマンドを作る方法をご紹介(自作スラッシュコマンド)  (1-0) やりたいこと  (1-1) STEP1:Slackボットの開発(所要時間:60分)  ( …

pyenvの使い方(基礎編)をご紹介

  <目次> (1) pyenvの使い方(基礎編)をご紹介  (1-1) STEP1:インストール系のコマンド  (1-2) STEP2:バージョンの適用/切り替え系のコマンド  (1-3) …

Pythonでargparseを用いて引数を受け取って実行する方法

<目次> (1) Pythonでargparseを用いて引数を受け取って実行する方法  (1-1) argparseとは?  (1-2) 基本的な使い方  (1-3) サンプルプログラム (2) 参考 …

Bing AIのAPIを疎通(HelloWorld)

  <目次> (1) Bing AIのAPIを疎通(HelloWorld)  やりたいこと/概要  前提条件  STEP1:Bing Web Search APIにサインアップ  STEP2 …

Azure FunctionsでPythonのライブラリを追加する方法(依存関係解決)

  <目次> (1) Azure FunctionsでPythonのライブラリを追加する方法(依存関係解決)  (1-1) requirement.txtの設定手順  (1-2) 補足事項 …

  • English (United States)
  • 日本語
Top