はじめに
Pepperのアプリ開発にあたって、よく使われているライブラリや、独自のPythonモジュールをインポートする際、意図した通りにインポートされないという事象に出くわしたので、対処方法をこちらに記載します。
同じ問題に直面した際の一助として頂ければ幸いです。
前提条件
以下の環境で試しています。
- MacBook Pro Retina 2015 13inch
- Choregraphe 2.5.5.5
問題1) モジュールの修正が適応されない
独自にモジュールを実装して利用する場合、当然ですがそのモジュールを修正する必要が頻繁に生じます。
モジュールを修正して import
すれば良いはずですが、うまくいきません。
実際にどういうことが起こるのか、サンプルを用いて以下に記載していきます。
サンプルの概要
サンプルとして使用する Python モジュールは、文字列を引数で受け取ったら、Choregrapheのログに出力するだけの簡単な機能で実装しています。
① 独自モジュールが入っているディレクトリ
② 「AddLibPath」ボックスでライブラリのパスを指定しています。
- ライブラリパス指定は、pepperに外部モジュール追加してみる。とりあえずrequestsで。を参考してください。
③ 「Print Text」ボックスでは、文字列を受け取り、モジュールの関数を呼んでいます。
④ 正常にログに出力されています。
まずは独自モジュールを作ってボックスでインポート
簡単な独自モジュールを作ってみます。
# -*- 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)
次に、作ったモジュールをボックスでインポートして使ってみます。
def onInput_onStart(self, input):
from app_name import custom_modules
custom_modules.print_text(self, input)
正常にログに出力されますね。
モジュールを少し修正し、再実行してみましょう
#temp_text = "print: " + _text
temp_text = "プリント: " + _text
あれ、変わってない…
本サンプルでは同一の関数内で出力を変えているだけですが、
例えば修正後のモジュールで新しい関数を追加して呼び出すと、エラーが発生してしまいます。
解決方法
モジュール実行前に明示的にリロードしましょう。
アプリ起動後の初期化処理時などに組みこむといいかと思います。
import app_name
reload(app_name)
import app_name.custom_modules
reload(app_name.custom_modules)
そのあと、実行してみると
意図通り修正内容が適応されてることが確認できます。
問題2) 意図しないライブラリをインポートしてしまう
例えば、Pepper 内にすでにインストールしてあるライブラリの異なるバージョンをlibの直下に置いてインポートすると、自分がプロジェクトに入れたバージョンを参照せず、Pepper 内のバージョンを参照することがあります。
(正確には import
する際の sys.path
値の順序に依存します)
下記の例を見てみましょう。
__lib__の直下に__v2.6.0__の__requests__モジュールを置きます。
その後、インポートし、
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)
エラーが発生してしまいました。
参照している__requests__のバージョンを見てみると、__v2.6.0__ではなく、__v2.3.0__になっています。
v2.3.0 は NAOqi OS 2.5.5 に元々インストールしてある requests のバージョンです。
従って、v2.3.0 よりあとのバージョンで追加された機能は使用できないのです。
解決方法
__lib__の直下に、__自身のアプリのID__などのディレクトリを作り、__init__.py ファイルと入れたいライブラリを入れます。
独自の名前空間を持ったパッケージを作る感じですね。
その後、正しいパスを指定しインポートして、再度、実行してみると
from app_name import requests
意図通り__v2.6.0__のrequestsモジュールが参照され、機能も無事使えるようになります。
まとめ
- 独自モジュールの変更内容が適応されない時は、明示的にリロード
- 独自のパッケージ名で名前空間を分けてから
import
を行う