日々ラズパイにお世話になっている割には「ラズパイを知らない」です。それに増しても、いつもの定型的な利用には問題なく使えすぎているので時々深みにはまったときの狼狽にダメージが大きいです。今回はラズパイ上のPythonで連発。何時にも増してローカルねた。
※「トホホな疑問」投稿順Indexはこちら
今回やろうとしていることは、これまたありがちな以下のような事であります。
ラズパイにカメラをつけて、人感センサのトリガで写真をとり、サーバ経由でパソコン上のブラウザでとった写真を見られるようにする
それほど難しくない、という判断。本日はその「準備」ということで。
ラズパイ・カメラの接続先
手元にあるラズパイ用のカメラモジュール、最近までRaspberry Pi 3B(以下Pi3)に接続してあったのですが取り外しました。別件でNode-RED動かしたり、HDDを接続したりして「すっかりサーバ化」してしまった為に持ち運びが不便になったためです。カメラの接続先としてはWiFiで運用できるRaspberry Pi Zero Wが適切と思ったのですが、
Pi Zeroのカメラ端子は異なる
ために手元のカメラのフレキが刺さりませぬ。「在庫0で買えないでいるRaspberry Pi PICOを発注するとき、ついでにZero用のカメラも」ということでとりあえず「遊休化している」Raspberry Pi model B+(以下Pi1)に接続。カメラの接続と撮影自体は「IoT何をいまさら(33) Raspberry Pi Camera」で一度やっておりまするで、問題ありませぬ。
拡張端子の信号を取り出しやすくしたい
ケース内部のピンヘッダには配線繋ぎにくいです。そこでエイヤと「ピンソケット3段」の「タワー」を作り信号線をケース外部のピンソケットに取りい出しました。最上部のアイキャッチ画像を御覧ください。これのお陰で信号線位置を間違えないように「印」をつけるスペースもまた確保。これが意外と便利。下の写真を御覧じろ。
とりあえず、テスト用に人感センサでなく、タクトスイッチとLチカ用のLEDを取り付けましたるところがこちら。
ハードウエアのとりあえずの道具立ては一応OK。次はソフトウエアです。今回は、
フルPython
でやりたい、という方針。
VS Codeでリモートの制限
最近、別件のmicro:bit用のMicroPythonを書くときにはPi3上でMuエディタを使っております。これはこれで中々良いものなのですが、普段MicroでないPythonをパソコン上で書くときにはVS Code使っています。Pi3に関してはパソコン上のVS Codeからリモートで編集可能であります。しかしここで問題、
VS Codeがリモート接続できるArmアーキテクチャはArmV7l以降
なのであります。逆にいうとArm11(ArmV6)搭載のPi1やPi Zeroは対象外なのであります。なおArmV7lの末尾のlはリトルエンディアンのlだそうです(一応、Armはビッグでもリトルでも出来る、ということになっているけれど、昔はともかく最近はビッグの実装を聞かない。。。)
「逃げのソリューション」?として、Pi3の作業用のディレクトリをNFSでPi1やPi ZEROからマウントするようにいたしました。とりあえずVS Codeの編集結果はPi1からも見える、と。
Python3のバージョン合わせたい、トホホ1勃発
Pi3上でVS Codeで編集、テストなどしたコードをそのままPi1でも使いたい、という「当然の」要求から、できればPython3のバージョンも合わせたいという希望を持ちました。ただ、Pi1とPi3では運用中のOSのバージョンが大分違います。
-
- Pi3、Raspbian buster、Python3のバージョンは3.7.3
- Pi1、Raspbian jessie、Python3のバージョンは3.4
Pi1上のAptコマンドではPython3.7.3などはインストールできそうになかったのでつい魔がさしました。「ソースからビルドすればいいんじゃね」。Python自体のビルドは、「configureして、makeして、make install」というお作法通りでできるみたいです。ちょうど同じようなことをされた方がおられて「Raspberry PiにPython3.7.2をインストール」、簡単そうに思えました。さっそく、こちらは3.7.3のソースをダウンロードしてきてビルド開始。非力で1コアのPi1上でのビルドなので、大体の時間は(別なことの横で走らせていたので気付いたらそのくらいの時間で終わっていたという)
-
- configure 15分
- make 2時間
- make install 30分
その間、1個しかないCPUは100%です。LOGも見もせずに終わった終わったと喜んでいたら足をすくわれました。PIPしたら、エラーでました。
pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.
駄目じゃん。とりあえずPython「動いて」はいるけれどもpipできなければ手足が無いのも同然。どうするか、ということでこの対処はトホホ2の後で。なにせ、ビルドに時間かかるので待ってられません。
nginxのcgiとしてPython3のスクリプトを走らせたい、トホホ2勃発
上記Pi1上のトホホ1の横で、サーバー機たるPi3上でもトホホ2が勃発しておりました。一応「サーバー機」なので用もないのにhttpサーバーとして nginxを動かしてあったのです。以前だったら Apache だったでしょうが、ようやく遅ればせながら nginx であります。とりあえずサーバ側としては
Python3のスクリプトをcgiとして実行できればいいんじゃね
というノリです。Pi1がNFSを通じて写真を所定のディレクトリに貯めておいてくれたらcgiで読み出せば見えるだろ、というお手軽。しかし、nginxでcgi、どうやるの?これまた先覚者様のよい資料ありました。
結論から言えば、上記の通りにやって動作OKでした。しかし、その途中、
502 BAD GATEWAY
エラーが出まくってトホホ。さんざんfcgiwrapの設定が間違っているのではないかと疑って時間つかってしまった。断言できます、
nginxのerror.logを見ればすぐわかった
logみたら、テスト用の用意したPython3のスクリプト内でエラーが発生していました。コマンドラインからは正常に動作したスクリプトなのに何故?
調べていくと原因は簡単。スクリプトの中で呼んでいるモジュールがcgiでは見つからなかったのです。コマンドライン実行時に見えているPython3のsite-packagesディレクトリがcgiで実行するときには見えていないのでした。理由は何のことはないです。コマンドラインのときとCGIのときでは「ユーザー」が違うから。コマンドラインからPIPでいれたモジュールはユーザーのホームディレクトリの下の .local の配下の奥にあるsite-packagesに入ってます。cgi実行ではそんなこと知らないのでそのモジュールは見えなかった、というだけ。sys.pathを操作するか、インストールするパスを変えるかすれば動作する筈。
トホホ1の対処、端から総当たり?
結局のところ、SSL関係のライブラリのバージョンとPythonのバージョンの不一致が問題である、と思われます。古いバージョンのPythonであれば、古いライブラリを必要とするし、新しいバージョンのPythonは新しいライブラリが必要、と。いたしかたありません。問題は、古い jessie バージョンのOS上の apt で「最新版」にアップデートしたライブラリで、どのバージョンのPythonならエラーなくビルドできるかというところ。ちゃんとドキュメントを調べりゃいいのでしょうが、結果オーライ路線で「上からだいたい順に試してみる」ことにいたしました。ただ、手動で、configure, make。。。としていくのもだるいし、後々考えると複数バージョンのPython共存ということにもなりそうなので、導入させていただいたのが、
pyenv
であります。複数バージョンのPython処理系を切り替えられる優れもの。これとvenvを組み合わせれば「最強」というのが「Raspberry PiにpyenvをインストールしてPythonをバージョン管理」に書かれてありました。その通りにいたしました。pyenvは複数の処理系を切り替えられるだけでなく、ソースをフェッチしてきて、ビルドするところまで勝手にやってくれます。ま、ビルドそのものは手動と同じなのでPi1上では
Installing Python-3.7.0…
などという表示のまま何時間かかかります。ライブラリが不適合で、失敗するとBUILD FAILEDなど素っ気ないです。そういうわけで 3.7.3につづき、3.7.0も駄目でした。続いて
$ pyenv install 3.6.0 Downloading Python-3.6.0.tar.xz... -> https://www.python.org/ftp/python/3.6.0/Python-3.6.0.tar.xz Installing Python-3.6.0... Installed Python-3.6.0 to /home/pi/.pyenv/versions/3.6.0
あれれ、3.6.0はエラーなし、できている。まずはpyenv機能のlocalをつかってこのPython 3.6.0設定で、venv作ってactivate。この環境下でPIPしてみました。installしてみるのは
RPi.GPIO
Raspberry Piの拡張端子を操作するための定番のモジュールであります。インストールOK。テスト用のLチカとタクトスイッチの読み出しPythonスクリプトも動作OK。
まあ、3.4から3.6に上げるのに大騒ぎだったな。Pi1の古い jessie を入れ替えないのが悪いのだけれど。。。