[OCI]Computeインスタンスにjupyter notebookをインストールし、ADB接続する(OL8)

# 1. はじめに
Compute に jupyter notebook をインストールし、python で ADB に接続してみます。
以下のライブラリを使用します。

| インストールするライブラリ |
|:-|
| python-oracledb  |
| sqlalchemy  |
| pandas  |


### 前提条件
https://qiita.com/twakimura/items/576d569bf195ef81280e
この記事を参考に Compute インスタンスから ADB への接続設定を行っています。

# 2. python のバージョン更新
oracleDB に接続するためのライブラリ python-oracledb は Linux8 にデフォルトでインストールされている python3.6 では非推奨となっています。

    $ python --version
    Python 3.6.8

そのため、利用する python のバージョンを3.8に更新します。
以下で python3.8 をインストールします。

    $ sudo dnf install -y gcc gcc-c++ make
    $ sudo dnf install -y python38

ですが、 python3.8 をインストールしただけではデフォルトの python バージョンが変わりません。

    $ python --version
    Python 3.6.8
    $ python3.8 --version
    Python 3.8.17

alternatives でデフォルトの python を変更します。
ここでは4番に python3.8 がリストされていたため、4をデフォルトに指定しています。

    $ sudo alternatives --config python

    There are 4 programs which provide 'python'.

      Selection    Command
    -----------------------------------------------
    *  1           /usr/libexec/no-python
       2           /usr/bin/python2
     + 3           /usr/bin/python3
       4           /usr/bin/python3.8

    Enter to keep the current selection[+], or type selection number: 4
    $ python --version
    Python 3.8.17
    
デフォルトの python バージョンを3.8に変更することが出来ました。

# 3.jupyter notebookのインストール
ここでは oracle ユーザーのhomeディレクトリに python というディレクトリを作成し、そこを python のhomeディレクトリとしています。

    $ sudo dnf update
    $ sudo dnf install python3-pip -y
    $ sudo python -m pip install --upgrade pip
    $ sudo su - oracle
    $ mkdir python
    $ cd python
    $ python -m pip install jupyterlab

上記を実行すると、以下のエラーが発生しました。

        SyntaxError: future feature annotations is not defined

        ----------------------------------------
    Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-wcm5l4hb/argon2-cffi-bindings/

同様のエラーが発生する場合は、以下の手順で解消できるようです。

    # pip3 install --upgrade pip setuptools
    # pip3 install ez-setup

上記を実行した後、再度 jupyter-lab をインストールしてみます。

    # sudo su - oracle
    $ cd python
    $ python -m pip install jupyterlab
    $ jupyter-lab --ip='0.0.0.0' --NotebookApp.token=''

jupyter が起動したら、起動ログに以下のようなURLが表示されます。

     Jupyter Server 2.14.2 is running at:
     http://<Instance名>:8888/lab
      or http://127.0.0.1:8888/lab

teraterm のSSH転送設定で以下を設定します。

ローカルのポート：8888
リモート側ホスト：localhost
ポート：8888

この状態でブラウザで以下のURLにアクセスすると、teraterm の転送設定で Compute インスタンス上で起動した jupyter notebook にアクセスできます。
http://localhost:8888/lab

jupyter notebook を起動したディレクトリがhomeディレクトリになるため、以下のように alias を切って同じディレクトリがhomeになるようにしておくと便利です。

    alias notebook="cd ~/python && jupyter-lab --ip='0.0.0.0' --NotebookApp.token=''"

# 3.pythonからのADB接続
テーブルにデータを用意します。

    SQL> CREATE TABLE TEST
     (TESTNO NUMBER(2) PRIMARY KEY,
     TESTNAME VARCHAR2(14));
    SQL> INSERT INTO TEST VALUES (1, 'テスト1');
    SQL> INSERT INTO TEST VALUES (2, 'テスト2');
    SQL> commit;

python から oracledb に接続するためのパッケージ python-oracledb と sqlalchemy をインストールします。
取得データの表示に pandas も利用するためあわせてインストールしておきます。

    $ pip3 install oracledb
    $ pip3 install sqlalchemy
    $ pip3 install pandas

ADBへの接続に必要な情報をoracleユーザーの環境変数に設定します。
TNS_ADMIN同様、.bashrcなどに記載しておくと便利です。

    $ export ORAUSER=admin
    $ export ORAPASS=<adminユーザーのパスワード>
    $ export ORATNS=<tnsnames.oraで確認した接続文字列>
    $ export WALLETPASS=<walletのパスワード>

環境変数を設定したユーザーで再度　jupyter notebook を起動し、以下の　python　コードを実行します。

```python:select.ipynb
import os
import pandas as pd
from sqlalchemy import create_engine

# 環境変数から情報を取得
un = os.environ.get('ORAUSER')
pw = os.environ.get('ORAPASS')
cs = os.environ.get('ORATNS')
wallet_dir = os.environ.get('TNS_ADMIN')
wallet_pw = os.environ.get('WALLETPASS')

# SQLAlchemyエンジンを作成
engine = create_engine(f'oracle+oracledb://{un}:{pw}@{cs}', connect_args={
    "config_dir": wallet_dir,
    "wallet_location": wallet_dir,
    "wallet_password": wallet_pw
})

# クエリ実行とデータ取得
query = "SELECT * FROM TEST"
with engine.connect() as conn:
    df = pd.read_sql(query, con=conn)

df
```


テーブル内容をpandasのDataframeで取得することができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514221/1e920db0-08bd-be73-46c4-bc8c380011cf.png)


# 4. データの挿入
ここではcsvファイルからデータinsertしてみます。
以下のcsvを用意します。

```csv:data/test.csv
"TESTNO","TESTNAME"
3,"テスト3"
```

pythonのコードは以下です。

```python:insert.ipynb
import os
import pandas as pd
from sqlalchemy import create_engine

un = os.environ.get('ORAUSER')
pw = os.environ.get('ORAPASS')
cs = os.environ.get('ORATNS')
wallet_dir = os.environ.get('TNS_ADMIN')
wallet_pw = os.environ.get('WALLETPASS')

# SQLAlchemyエンジンを作成
engine = create_engine(f'oracle+oracledb://{un}:{pw}@{cs}', connect_args={
    "config_dir": wallet_dir,
    "wallet_location": wallet_dir,
    "wallet_password": wallet_pw
})

# データの準備
csv = 'data/test.csv'
df = pd.read_csv(csv)

# 既存のテーブルにデータを挿入（テーブル名は小文字で指定）
with engine.connect() as conn:
    # 既存のテーブルにデータを追加
    df.to_sql('test', con=engine, if_exists='append', index=False)

# 接続を閉じる
engine.dispose()
```

上記はinsertまでのコマンドサンプルですので、再度照会コマンドを実行するとデータが挿入されていることが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514221/e05c93d7-9f6b-7e78-f2f7-e0745082bb28.png)