Loading [MathJax]/extensions/tex2jax.js

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) エラーメッセージ
  1. sqlalchemy.exc.ArgumentError: Could not parse rfc1738 URL from string '[Table name]'

 

(1-1-2) エラーとなったソース
  1. import datapackage
  2. import cx_Oracle
  3. import sqlalchemy
  4. import pandas as pd
  5. import requests
  6. from io import StringIO
  7.  
  8. def main():
  9. 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'}
  10. url = 'https://[your URL].json'
  11. dp = datapackage.Package(url)
  12. res = dp.resources
  13.  
  14. from sqlalchemy import create_engine
  15. engine = create_engine('oracle://[your schema]:[your password]@[hostname]:[port]/[sid]')
  16. for res in res:
  17. if res.tabular:
  18. if res.descriptor['datahub']['type'] == 'derived/csv':
  19. s=requests.get(res.descriptor['path'], headers= headers).text
  20. df = pd.read_csv(StringIO(s))
  21. print(res.descriptor['path'])
  22. df.to_sql(engine,'CMTB_COMPANY_MASTER',if_exists='replace',index=False)
  23.  
  24. if __name__ == '__main__':
  25. main()
  26.  

(図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”の順番を逆にしたら、当該エラーは起こらなくなりました。
(ただし、今度は後述の別のエラーに遭遇しますが・・)

  1. 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) エラーメッセージ
  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しています。

  1. import datapackage
  2. import cx_Oracle
  3. import sqlalchemy
  4. import pandas as pd
  5. import requests
  6. from io import StringIO
  7.  
  8. def main():
  9. 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'}
  10. url = 'https://[your URL].json'
  11. dp = datapackage.Package(url)
  12. res = dp.resources
  13.  
  14. from sqlalchemy import create_engine
  15. engine = create_engine('oracle://[your schema]:[password]@[hostname]:[port]/[sid]')
  16. for res in res:
  17. if res.tabular:
  18. if res.descriptor['datahub']['type'] == 'derived/csv':
  19. s=requests.get(res.descriptor['path'], headers= headers).text
  20. df = pd.read_csv(StringIO(s))
  21. print(res.descriptor['path'])
  22. df.to_sql('CMTB_COMPANY_MASTER',engine,if_exists='replace',index=False)
  23.  
  24. if __name__ == '__main__':
  25. main()

(図201)

目次にもどる

(2-2) 原因

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

  1. 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.
  2. warnings.warn(msg, UserWarning)

目次にもどる

(2-3) 対処方法

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

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

■修正後:

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

(図202)
・エラーは解消


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

目次にもどる

Adsense審査用広告コード


Adsense審査用広告コード


-Python

執筆者:


comment

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

関連記事

no image

Azure Cognitive Searchを行うPythonプログラム(ドキュメント検索)

  <目次> Azure Cognitive Searchを行うPythonプログラム(ドキュメント検索)  STEP0:前提条件  STEP1:キーとURLの取得  STEP2:セマンティ …

no image

PythonでJSON形式データの値を取得する手順について

  <目次> (1) PythonでJSON形式データの値を取得する手順について  (1-1) サンプル①:ローカルのJSONファイルの読み込み(単純構造)  (1-2) サンプル②:ローカ …

pyenvのインストール手順(Windows10の例)

  <目次> (1) pyenvのインストール手順(Windows10の例)  (1-1) pyenvとは?  (1-2) pyenvのインストール手順 (1) pyenvのインストール手順 …

Python開発環境にPandasライブラリをインストールする手順

(0)目次&概説 (1) Pandasの導入  (1-1) Pandasとは? (2) オフラインインストール  (2-1) インストール資源の入手  (2-2) インストール時の諸注意  (2-3) …

Pythonのコンストラクタの基礎と「self」や「__init__」について

<目次> (1) Pythonのコンストラクタの基礎と「self」や「__init__」について  (1-1) 「__init__」やコンストラクタについて  (1-2) コンストラクタで使われる「s …

  • English (United States)
  • 日本語
S