Posted at

SQLAlchemyを使ってOracleに接続する

DockerでDjango環境を作成 の続きです。

SQLAlchemyを使ってOracleに接続するまでに行った手順を記載しています。


(1) 準備:テーブル作成

下記のようなデータを持つテーブル(GYUNYU_MASTER)をOracleに作成しました。

id
name

1
コーヒー牛乳

2
いちご牛乳

3
れもん牛乳


(2) SQLAlchemyをインストール

python/work/requirements.txtsqlalchemyを追記。


python/work/requirements.txt

django==2.0.3

uwsgi==2.0.17.1
sqlalchemy==1.2.6

1.docker-compose up --build -dを実行してコンテナの生成&起動する。

2.docker exec -it コンテナ名 bashを実行してコンテナの中に入る。

3.pythonを起動して下記を実行し、SQLAlchemyがインストール出来ている事を確認する。

>>> import sqlalchemy

>>> sqlalchemy.__version__

4.Oracleへ接続するためのデータベースエンジンの設定を追記。


gyunyu/__init__.py

from sqlalchemy import create_engine

from sqlalchemy.orm import sessionmaker

engine = create_engine("oracle://ID:パスワード@IPアドレス:ポート番号/データベース名" echo=True)
Session = sessionmaker(bind=engine)


5.セッションを管理する関数を追記。


gyunyu/__init__.py

from contextlib import contextmanager

@contextmanager
def session_scope():
session = Session()
try:
yield session
except:
raise
finally:
if session is not None:
session.close()


6.views.pyにDBから値を取得する処理を追記。


coffee/views.py

from django.shortcuts import render

from django.http import HttpResponse
from gyunyu import session_scope

def index(request):
with session_scope() as session:
result = session.execute("select * from gyunyu_master")
rows = result.fetchall()
return HttpResponse("Coffee Gyunyu !!! {}".format(rows))


下記のようなエラーが発生しました。

No module named 'cx_Oracle'


(3) cx_Oracleをインストール

1.python/work/requirements.txtcx_oracleを追記。


python/work/requirements.txt

django==2.0.3

uwsgi==2.0.17.1
sqlalchemy==1.2.6
cx_oracle==6.2.1

コンテナの再作成をしてアクセスすると、再びエラーが発生しました。

(cx_Oracle.DatabaseError) DPI-1047: 64-bit Oracle Client library cannot be loaded: "libclntsh.so: cannot open shared object file: No such file or directory". See https://oracle.github.io/odpi/doc/installation.html#linux for help (Background on this error at: http://sqlalche.me/e/4xp6)


(4) Oracle Clientのインストール

Oracle Clientが必要なようなので、Instant Clientをこちらからダウンロードしました。

今回は、instantclient-basic-linux.x64-12.1.0.2.0.zipをダウンロードしました。


  1. ダウンロードしたファイルをpython/workフォルダに保存して、python/Dockerfileに追記


python/Dockerfile

ENV ORACLE_HOME=/opt/oracle/instantclient_12_1

ENV LD_RUN_PATH=$ORACLE_HOME
ENV LD_LIBRARY_PATH=$ORACLE_HOME
ENV PATH=$PATH:$ORACLE_HOME

RUN apt-get update
RUN apt-get install -y unzip
RUN unzip instantclient-basic-linux.x64-12.1.0.2.0.zip -d /opt/oracle
RUN ln -s $ORACLE_HOME/libclntsh.so.12.1 $ORACLE_HOME/libclntsh.so


コンテナの再作成をしてアクセスすると、再びエラーが発生しました。

(cx_Oracle.DatabaseError) DPI-1047: 64-bit Oracle Client library cannot be loaded: "libaio.so.1: cannot open shared object file: No such file or directory". See https://oracle.github.io/odpi/doc/installation.html#linux for help (Background on this error at: http://sqlalche.me/e/4xp6)


(5) libaioのインストール

libaio.so.1が必要らしいので、インストールする設定をpython/Dockerfileに追記。


python/Dockerfile

RUN apt-get install -y libaio1


アクセス出来るようになりました。


(6) NLS_LANGを追記

上記までの作業でOracleからデータを持ってくる事はできたのですが、

nameに登録している文字列(全角文字)が化けていたので、下記をpython/Dockerfileに追記。

ENV NLS_LANG=Japanese_Japan.AL32UTF8

もう一度アクセスしてみると、文字化けも無く表示できました。


さいごに

最終的にpython/Dockerfileは、下記のようになりました。

FROM python:3.6

ENV LANG C.UTF-8
ENV TZ Asia/Tokyo

ENV ORACLE_HOME=/opt/oracle/instantclient_12_1
ENV LD_RUN_PATH=$ORACLE_HOME
ENV LD_LIBRARY_PATH=$ORACLE_HOME
ENV PATH=$PATH:$ORACLE_HOME
ENV NLS_LANG=Japanese_Japan.AL32UTF8

RUN mkdir /home/work
RUN mkdir /home/work/django
COPY work/ /home/work
WORKDIR /home/work
RUN pip install --upgrade pip
RUN pip install -r requirements.txt

RUN apt-get update
RUN apt-get install -y unzip
RUN unzip instantclient-basic-linux.x64-12.1.0.2.0.zip -d /opt/oracle
RUN ln -s $ORACLE_HOME/libclntsh.so.12.1 $ORACLE_HOME/libclntsh.so
RUN apt-get install -y libaio1

CMD ["uwsgi", "--ini", "/home/work/uwsgi.ini"]