Pepper のアプリで Python のライブラリや独自モジュールがうまくインポートされない時の対処法

# はじめに
Pepperのアプリ開発にあたって、よく使われているライブラリや、独自のPythonモジュールをインポートする際、意図した通りにインポートされないという事象に出くわしたので、対処方法をこちらに記載します。
同じ問題に直面した際の一助として頂ければ幸いです。

# 前提条件
以下の環境で試しています。

- MacBook Pro Retina 2015 13inch
- Choregraphe 2.5.5.5

# 問題1) モジュールの修正が適応されない
独自にモジュールを実装して利用する場合、当然ですがそのモジュールを修正する必要が頻繁に生じます。
モジュールを修正して `import` すれば良いはずですが、うまくいきません。
実際にどういうことが起こるのか、サンプルを用いて以下に記載していきます。

## サンプルの概要
サンプルとして使用する Python モジュールは、文字列を引数で受け取ったら、Choregrapheのログに出力するだけの簡単な機能で実装しています。

<img width="942" alt="スクリーンショット_はじめに.png" src="https://qiita-image-store.s3.amazonaws.com/0/172685/fbd31b96-9f28-190d-3633-4fe19d69c6ca.png">

① 独自モジュールが入っているディレクトリ
② 「AddLibPath」ボックスでライブラリのパスを指定しています。
* ライブラリパス指定は、[pepperに外部モジュール追加してみる。とりあえずrequestsで。](http://qiita.com/n0bisuke/items/5b782bb758ce5611cc90)を参考してください。
③ 「Print Text」ボックスでは、文字列を受け取り、モジュールの関数を呼んでいます。
④ 正常にログに出力されています。



## まずは独自モジュールを作ってボックスでインポート
簡単な独自モジュールを作ってみます。

```python:custom_modules.py
# -*- coding: utf-8 -*-

'''
app_name.custom_modules
独自モジュール
'''

# 引数をログに出力
def print_text(box_self, _text):
    '''
    ・引数
        _text : 出力する文字列
    ・結果
        _textをログに出力する    
    '''
    
    temp_text = "print: " + _text

    box_self.logger.info(temp_text)
```

- - -
次に、作ったモジュールをボックスでインポートして使ってみます。

```py
def onInput_onStart(self, input):
    from app_name import custom_modules

    custom_modules.print_text(self, input)
```

<img width="630" alt="スクリーンショット 2017-03-29 17.02.17.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/172685/27f79a36-a39c-0ab9-98fc-0c5f920491fe.jpeg">

正常にログに出力されますね。
- - -
モジュールを少し修正し、再実行してみましょう

```python:custom_modules.py
#temp_text = "print: " + _text
temp_text = "プリント: " + _text
```

<img width="630" alt="スクリーンショット 2017-03-29 17.02.17.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/172685/27f79a36-a39c-0ab9-98fc-0c5f920491fe.jpeg">

あれ、変わってない…

本サンプルでは同一の関数内で出力を変えているだけですが、
例えば修正後のモジュールで新しい関数を追加して呼び出すと、エラーが発生してしまいます。

## 解決方法

モジュール実行前に明示的にリロードしましょう。
アプリ起動後の初期化処理時などに組みこむといいかと思います。

```
import app_name
reload(app_name)
import app_name.custom_modules
reload(app_name.custom_modules)
```

そのあと、実行してみると

<img width="643" alt="スクリーンショット 2017-03-29 17.34.19.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/172685/deafc515-385c-dfef-960a-7d217bd33917.jpeg">

意図通り修正内容が適応されてることが確認できます。

# 問題2) 意図しないライブラリをインポートしてしまう

例えば、Pepper 内にすでにインストールしてあるライブラリの異なるバージョンをlibの直下に置いてインポートすると、自分がプロジェクトに入れたバージョンを参照せず、Pepper 内のバージョンを参照することがあります。
（正確には `import`する際の `sys.path` 値の順序に依存します）

下記の例を見てみましょう。

__lib__の直下に__v2.6.0__の__requests__モジュールを置きます。

<img width="361" alt="スクリーンショット 2017-03-29 17.47.17.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/172685/7fc11dfb-4e59-931a-c7a8-89f7bbc9fe6f.jpeg">

その後、インポートし、

```py
import requests 
```
__v2.4.2__の__requests__で追加された引数である_json__にパラメータを指定してPOSTをしてみると

```
url = 'https://api.github.com/some/endpoint'
payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.post(url, json=payload)
```

<img width="131" alt="スクリーンショット 2017-03-29 18.24.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/172685/08a9f6fb-01eb-8f87-4487-48de58dc8808.png">

<img width="635" alt="スクリーンショット 2017-03-29 18.26.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/172685/489071fa-c7f8-f27f-878a-5ed67283768e.png">

エラーが発生してしまいました。

参照している__requests__のバージョンを見てみると、__v2.6.0__ではなく、__v2.3.0__になっています。
v2.3.0 は NAOqi OS 2.5.5 に元々インストールしてある requests のバージョンです。
従って、v2.3.0 よりあとのバージョンで追加された機能は使用できないのです。

## 解決方法

__lib__の直下に、__自身のアプリのID__などのディレクトリを作り、\_\_init\_\_.py ファイルと入れたいライブラリを入れます。
独自の名前空間を持ったパッケージを作る感じですね。

<img width="361" alt="スクリーンショット 2017-03-29 18.00.41.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/172685/b85f1202-c0df-2d59-d611-038a691bcae8.jpeg">


その後、正しいパスを指定しインポートして、再度、実行してみると

```py
from app_name import requests 
```

<img width="630" alt="スクリーンショット 2017-03-30 10.16.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/172685/10a380fc-c62b-ffcb-2b5b-5925867eef84.png">

意図通り__v2.6.0__のrequestsモジュールが参照され、機能も無事使えるようになります。

# まとめ
1. 独自モジュールの変更内容が適応されない時は、明示的にリロード
2. 独自のパッケージ名で名前空間を分けてから `import` を行う