この記事はJPOUG Advent Calendar 2017の3日目です。 さらに同日にもう1記事あげていますのでよろしければご覧ください。
本記事では、sqlpylusを使用してPythonからOracle DatabaseにSQLを発行する流れをご紹介します。 なお、sqlpylusはsqlplusの誤植ではありません。
sqlpylus?
sqlpylusはPythonからOracle DatabaseにSQLを実行し、その結果を扱いやすいDict形式で取得するPython用のライブラリです。
以下READMEからの抜粋です。
sqlpylus はPython経由でOracleDatabaseにSQLを発行できるモジュールです。内部的にはSQLPLUSを起動し、その結果を標準出力経由で受け取って加工しています。
というか、この記事のために以前書き捨てていたコードを急いで整えたものになります。
こんな感じで比較的直感的に利用することが可能です。
import SqlPylus conn = SqlPylus().connect('scott', 'tiger', 'localhost:1521/orcl') for row in conn.execute('select empno, deptno from emp'): print(row['EMPNO'], row['DEPTNO']) conn.close()
何故作ったのか
sqlpylusはOCIを利用するcx_Oracleに比べるとSQLPLUSを裏で起動した上で処理しているためパフォーマンス・機能面すべてで劣っていますしかし、唯一のメリットとして1ファイルで構成されているため導入が簡単という点があります。
1ファイルで構成されているため、単一のPythonファイルを実行環境に配置できればそのまま利用できます。以下のような利用ケースを想定しています。 (果たしてこれらの用途でPythonを採用しているケースがどの程度あるかは不明ですが…)
- バッチ処理の一部での若干面倒なSQLの処理
- パフォーマンス監視等でSELECTの結果を整ったデータ形式で取得する簡易スクリプトへの組み込み
もちろん、これらのケースではcx_Oracle
を利用できればよいのですが、多くの場合このような環境はネットワークの制限が厳しかったり、pip
の導入ができなかったりといった理由でcx_Oracle
を採用できないケースが多い気がします。
sqlpylusはRedhat6やOracleLinux6系で標準でバンドルされているPython2.6以上で動作するため、このスクリプトさえ、配置できれば利用できます。できれば、Redhat5系でバンドルされているPython2.4もサポートしたいところなのですが、2.4になるとsubprocess関連が途端に貧弱になるので現状はやっていません。
利用方法
繋いでexecuteでSQLを実行するくらいですので大した内容はありませんが、 READMEにまとめています。
内部的な話
sqlplusの結果の表示形式は残念ながら結構崩れるので、そのままパースするのは少しつらいです。しかし、sqlplusは結果をHTML形式で戻すオプション(-M "HTML ON"
)があります。これを利用するとselect ename, empno from scott.emp where deptno=10;
の結果が以下のような形式で結果が戻されます。
ENAME | EMPNO |
---|---|
CLARK | 7782 |
KING | 7839 |
MILLER | 7934 |
HTMLとしては以下の形です。
<p> <table border='1' width='90%' align='center' summary='Script output'> <tr> <th scope="col"> ENAME </th> <th scope="col"> EMPNO </th> </tr> <tr> <td> CLARK </td> <td align="right"> 7782 </td> </tr> <tr> <td> KING </td> <td align="right"> 7839 </td> </tr> <tr> <td> MILLER </td> <td align="right"> 7934 </td> </tr> </table> <p>
あとは、これをTHタグとTDタグについて処理してやればJSONやPythonのDictのように整った形式に変換するのは難しくありません。
なお、number型の結果については
<td align="right"> 7934 </td>
という形でalign="right"
が付与されているので受け取る際にfloatにキャストしています。それ以外のデータ型は型情報が判別できないのでstr(unicode)として戻しています。
まとめ
単一スクリプトで利用できるPython用Oracle Databaseアダプタのsqlpylusをご紹介しました。最低限の機能しか実装していませんが、何かのご参考になれば幸いです。