読者です 読者をやめる 読者になる 読者になる

Raspberry Pi の Python 実行環境を整える

概要

USB ケーブル 1 本で Raspberry Pi Zero と接続できる様になったので、Python プログラムを Raspberry Pi Zero で動かしてみます。 しかし、今後の試行錯誤を考え、(自分にとっての)プログラムを作りやすい環境を整えてみました。 具体的には以下を行なっています。

  • ssh でのログインをパスワードなしにする
  • Python 2.x 系と 3.x 系を切り替えられる様にする
  • Mac でプログラムを作成し、Raspberry Pi Zero では実行のみ行う様にする

確認環境

参考情報

前回の記事

nosix.hatenablog.com

解説

ssh コマンドでパスワードを入力せずにログインする

前回、ssh コマンドでログインできる様になった。 しかし、ssh コマンドでログインする度にパスワードを入力するのは面倒だ。 そこで、公開鍵認証を使用してパスワード入力せずにログインできる様にする。

Mac で鍵ペアを生成して、公開鍵のみを Raspberry Pi の ~/.ssh/authorized_keys に登録する。 秘密鍵は絶対に外部に漏らしてはいけない。 ssh-keygen コマンドは鍵ペアを生成する。 鍵ペアは ~/.ssh ディレクトリに id_rsa (秘密鍵), id_rsa.pub (公開鍵) として生成される。 安全のためにパスフレーズ (passphrase) は入力した方が良い。 id_rsa.pub を Raspberry Pi の ~/.ssh/authorized_keys に登録する。

mac:~ nosix$ ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/nosix/.ssh/id_rsa): 
Created directory '/Users/nosix/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /Users/nosix/.ssh/id_rsa.
Your public key has been saved in /Users/nosix/.ssh/id_rsa.pub.
...省略...
mac:~ nosix$ scp ~/.ssh/id_rsa.pub pi@raspberrypi.local:~
id_rsa.pub                                    100%  404     0.4KB/s   00:00
mac:~ nosix$ ssh pi@raspberrypi.local
...省略...
pi@raspberrypi:~ $ mkdir .ssh
pi@raspberrypi:~ $ cat id_rsa.pub >> .ssh/authorized_keys
pi@raspberrypi:~ $ rm id_rsa.pub
pi@raspberrypi:~ $ exit

authorized_keys は存在していないため cat コマンドではなく mv コマンドでも構わないが、 既に authorized_keys が存在する場合には追記する必要がある。 cat src_file >> dst_file で追記できることを知っておくと便利かと思う。

以上で設定は完了したので、ssh コマンドでログインしてみる。 途中で接続を続けるかと尋ねられるので yes とする。 Raspberry Pi を識別するための情報(ECDSA key fingerpring)が Mac の ~/.ssh/known_hosts に登録される。 次回からは途中で尋ねられることなくログインできる。

mac:~ nosix$ ssh pi@raspberrypi.local
The authenticity of host 'raspberrypi.local (<省略>)' can't be established.
ECDSA key fingerprint is SHA256:<省略>.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'raspberrypi.local,<省略>' (ECDSA) to the list of known hosts.

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Fri Dec 16 04:36:43 2016 from <省略>
pi@raspberrypi:~ $ 

ログインできれば成功。 Raspberry Pi (の authorized_keys) に登録した Mac からはパスワードなしでログインできる。 Mac 側では ssh-keygen で入力したパスフレーズを 1 度だけ入力することがある。 パスフレーズで認証しておくことで、ssh でログインする際にはパスワードが不要になる。 パスワードは passwd コマンドで複雑なパスワードに変更する。

~/.bash_profile にコマンドのエイリアス(別名)を登録しておくと便利。 以下の 1 行を追加すると pish コマンドで Raspberry Pissh でログインできる。

alias pish='ssh pi@raspberrypi.local'

PC に再ログインした場合には、ssh-add コマンドを実行して認証する。 認証が完了していない場合には、ssh の実行の際にパスフレーズの入力が求められる。

mac:~ nosix$ pish
Enter passphrase for key '/Users/nosix/.ssh/id_rsa':

Python3 環境を Raspberry Pi に作る

Python には 2.x 系と 3.x 系が存在する。 2.x 系と 3.x 系で異なる部分があり、2.x 系で動くからと言って 3.x 系では動かないという場合がある。 もちろん、反対もあり得る。 Raspberry Pi に標準でインストールされている Python は 2.x 系。 3.x 系の Python も導入し、2.x 系と 3.x 系を切り替えられる様にしておく。

Raspberry Pi に python3, pip (Python のパッケージ管理ツール), virtualenv (実行環境を切り替えるツール) をインストールする。 pip を使うことで、多くの人が作ってくれた Python の便利道具(パッケージ)を簡単に導入できる。 パッケージにはバージョンがあり、バージョンの組み合わせによっては動作しないこともある。 様々な実験を行うために個別の実験室(仮想環境; virtualenv)を用意しておくと便利。(実験室は比喩。) パッケージを導入する際には実験室を指定して導入し、他の実験室には影響が及ばない様にする。 また、実験室毎に Python2 と Python3 のいずれを使うかを決めておくことができる。

まず、Raspberry Pi からインターネットに接続できる様にする。 Mac でインターネット共有を設定する。 RNDIS/Ethernet Gadget にチェックを入れる。

次に、python3, python3-rpi.gpio, pip, virtualenv をインストールする。

pi@raspberrypi:~ $ sudo apt-get install python3
...省略...
pi@raspberrypi:~ $ sudo apt-get install python3-rpi.gpio
...省略...
pi@raspberrypi:~ $ sudo apt-get install python-pip
...省略...
pi@raspberrypi:~ $ sudo pip install virtualenv
...省略...

実験室 (仮想環境; virtualenv) を作成する。 例では、~/pyenv/python2, ~/pyenv/python3 を作成している。 apt-get で install した python3-rpi.gpio を使用するために、--system-site-packages を指定している。 (ディレクトリはお好みで。)

pi@raspberrypi:~ $ mkdir ~/pyenv
pi@raspberrypi:~ $ virtualenv -p python2 ~/pyenv/python2
Running virtualenv with interpreter /usr/bin/python2
New python executable in /home/pi/pyenv/python2/bin/python2
Also creating executable in /home/pi/pyenv/python2/bin/python
Installing setuptools, pip, wheel...done.
pi@raspberrypi:~ $ virtualenv --system-site-packages -p python3 ~/pyenv/python3
Running virtualenv with interpreter /usr/bin/python3
Using base prefix '/usr'
New python executable in /home/pi/pyenv/python3/bin/python3
Also creating executable in /home/pi/pyenv/python3/bin/python
Installing setuptools, pip, wheel...done.

試しに実験室に入る。activate を source コマンドで読み込むと仮想環境が有効になる。

pi@raspberrypi:~ $ source ~/pyenv/python3/bin/activate
(python3) pi@raspberrypi:~ $ 
(python3) pi@raspberrypi:~ $ python --version
Python 3.4.2

実験室から出る(仮想環境を無効にする)には、deactivate コマンドを使う。

(python3) pi@raspberrypi:~ $ deactivate 
pi@raspberrypi:~ $ 

以降、pip でパッケージをインストールする際には、実験室に入ってから行う。 全ての実験室で共通して使いたいパッケージの場合には、実験室に入らずに pip でインストールする。

Mac 環境でソースコードを作成して、Raspberry Pi で動かす

Raspberry Pi で IDLE を使用してソースコードを編集しても良いが、Mac 環境の方がツールも多く便利である。 Mac 環境でソースコードを作成して、Raspberry Pi にコピーして Raspberry Pi で実行する仕組みを用意する。 (この節の内容は試行中のものです。)

~/bin/pidep コマンドを自作する。(dep は Deploy の意。) Mac から Raspberry Pi にファイルを scp でコピーして、Mac から ssh で実行するスクリプトになっている。

コマンドを実行できる様にする。

mac:~ nosix$ chmod +x ~/bin/pidep

Raspberry Pi に ~/pyhome ディレクトリと仮想環境 ~/pyenv/python3 を用意しておく。

pi@raspberrypi:~ $ mkdir ~/pyhome

pidep の PI_HOME と PI_ENV で指定している。 PI_HOME はコピー先のルート、PI_ENV は実行時に使用する仮想環境の指定。

使い方

まずは、Python3 プログラム(hello.py)を用意する。1 秒毎に Hello と表示される。

from time import sleep

while True:
    print("Hello")
    sleep(1)

このプログラムを pidep で Raspberry Pi にコピーして実行する。 -s はコピー元、-r は実行するプログラム(スクリプト)を指定する。

mac:tmp nosix$ pidep -s hello.py -r hello.py
hello.py                                      100%   68     0.1KB/s   00:00    
Hello
Hello
Hello
Hello
^CTraceback (most recent call last):
  File "hello.py", line 5, in <module>
    sleep(1)
KeyboardInterrupt
Connection to raspberrypi.local closed.

-d でコピー先を指定できる。 -r を省略するとコピーのみ、-s を省略すると実行のみ行われる。

mac:tmp nosix$ pidep -s hello.py -d loop.py -r loop.py
mac:tmp nosix$ pidep -r hello.py
mac:tmp nosix$ pidep -s hello.py