Upgrade to Pro — share decks privately, control downloads, hide ads and more …

社内用Python基礎講習テキスト

Saito5656
February 05, 2020

 社内用Python基礎講習テキスト

少人数でラズパイIoTハンズオンをやらないかという声掛けがあり、自己啓発で習得した初歩的スキルを棚卸して簡単なハンズオン資料を作りました。

残念ながらコロナ禍でオフラインイベントが軒並み中止になり自然消滅しましたが、勤務先社内の有志と共有するためのハンズオン資料として構成しなおして勤務先に提供しました。

現在でも社内で不定期開催される入門講習のテキストとして利用しています。

2022.5.1追記
社内講習テキストの元となるAWS IoT設定まで含めた個人講習用テキストに置き換えます。OSバージョンとGUIが数世代前の情報になりますが自分が関わり始めた初期の参考資料としてこのまま残します。(現在はAWSCLIとSAMで簡単らくちんに実装しています)

対象:Python未経験者、プログラミング未経験者も可

所要時間:3~4日

Saito5656

February 05, 2020
Tweet

More Decks by Saito5656

Other Decks in Programming

Transcript

  1. 学習内容 0章. RaspberryPiを使う理由 1章. RaspberryPi OS(Linux)のインストール 1-1 OSイメージのダウンロード 1-2 各種アプリのインストール

    1-3 OSのインストール 1-3 ファイル交換アプリのインストール 2章. RaspberryPi (Linux)の環境構築 2-1 よく使うLinuxコマンド 2-2 通信環境 2-3 rootfsのROM化 2-4 update/upgrade 2-5 日本語環境 2-6 MQTTモジュール(paho/mosuqitto)インストール 2-7 画像処理モジュール(openCV)インストール 2-8 ユーザー作成と公開鍵認証 2-9 iptables(LinuxのFW)の設定
  2. 学習内容 3章. Python基礎 3-1 Pythonの学び方 3-2 Hello world!(コメントとインデント) 3-3 数値型と文字列型

    3-4 シーケンス型(list型、tuple型、 3-5 set型、マッピング型(dictionary) 3-6 制御フロー(if 文、elif、else、for文) 3-7 制御フロー(while文、continue、break) 3-8 ライブラリー・モジュール・クラス・メソッド 3-9 関数 3-10 ファイル操作 3-11 画像取得(openCV) 3-12 例外処理 課題 3-13 nanoエディタでhello.pyをつくる 3-14 GPIOで光センサーデータを読込む 3-15 センサートリガーで画像取得する
  3. 0 RaspberryPiを使う理由 会社PCでlinux開発環境つくるには情シ部検証の時間が必要 そもそも教育用のPCボードとして開発された ・Linux環境の学習にもってこい ・安価(本体:5,000~6,500円) 安価でも能力は一昔前のDesktop並み ・クアッドコア 1.5MHz (4B)・RAM

    1~4GB(4B) RaspberyPiの「Pi」は「Python」に由来 ・OS標準でPython導入済み GPIO、カメラ、USB、R45Jポートを標準装備 RaspberryPi 3B以降は標準で有線/無線LAN接続が可能 ラインサイドの機械学習の推論用デバイスにも利用可能 ・Google Edge TPU等と組合わせるとJetsonNano並み
  4. 構築内容 rootfs ROM化 tmpfs(/mnt/root-rw) /dev/mmcblk0p2(/mnt/root-ro) Read/Write要求 … … 外部ライブラリー導入 公開鍵認証

    公開鍵 秘密鍵 〇:newuser ×:root ×:pi root/pi ユーザー無効化 フィルター(iptables)設定 通信設定
  5. 2-1 よく使うLinuxコマンド poweroff システムのシャットダウン reboot システムの再起動 ls ファイルやディレクトリの情報表示 cd ディレクトリ(フォルダ)の移動

    mkdir フォルダを作成 cp ファイルやディレクトリのコピー mv ファイルやディレクトリの移動 ファイル名変更やディレクトリ名変更 rm ファイルやディレクトリの削除 cat ファイルの中身をテキスト表示 nano等でも表示できるが表示だけならcatが安全 chmod ファイルやディレクトリのアクセス権変更 nano テキストエディタnanoで編集 ファイル名が存在しなければ新規ファイル作成となる hostname ホスト名やIPアドレスの表示 ifconfigでもIPアドレス取得できる apt-get パッケージの管理 pip Pythonで書かれたパッケージの管理 Python3系ではsudo pip3 install “パッケージ名” となる passwd ユーザーのパスワード変更 raspi-config RaspberryPiの設定ツール、CUIで必要 wget ファイルのダウンロード その他、必要に応じて検索すると結構簡単にヒットする
  6. 2-2 通信環境構築(SSID変更時) sudo raspi-configを実行しSSIDとパスフレーズを設定してwifi接続 sudo raspi-configを実行 Network Optionsを選択 N2 Wi-fiを選択

    接続先のSSIDを入力(ここでは携帯のSSID) 接続先のSSIDのパスフレーズを入力 …. ifconfigを実行して ip(ここではデザリング先が返す)と グローバルipが帰ってきてるので 接続成功しているのがわかる
  7. 2-3① rootfsのROM化 実行するコマンド cd /home/pi sudo bash # 必要なパッケージ類 echo

    Installing all dependencies apt-get install git subversion rsync gawk busybox bindfs # swapを使用しないように echo Disabling swap dphys-swapfile swapoff dphys-swapfile uninstall update-rc.d dphys-swapfile disable systemctl disable dphys-swapfile #gitクローン echo Cloning repository git clone https://github.com/josepsanzcamp/root-ro.git # 設定 echo Doing the setup rsync -va root-ro/etc/initramfs-tools/* /etc/initramfs-tools/ mkinitramfs -o /boot/initrd.gz echo initramfs initrd.gz >> /boot/config.txt # 再起動 echo Restarting RPI reboot bootがroになってる 連続利用が前提なのでboot後はmicroSDカードに書き込みさせない
  8. 2-3② rootfsのROM化解除 実行するコマンド #!/bin/sh if [ -e /mnt/boot-ro/config.txt ]; then

    sudo mount -o remount,rw /dev/mmcblk0p1 sudo grep -v initramfs /mnt/boot-ro/config.txt >/tmp/config.txt sudo cp /tmp/config.txt /mnt/boot-ro/config.txt sudo reboot else echo Already write enabled fi bootがroになる ROM化に成功したら環境構築を続けるので書込み禁止を解除
  9. 2-4 update/upgrade 実行するコマンド sudo apt update sudo apt dist-upgrade -y

    sudo apt upgrade -y ROM化後にOSを最新の状態に更新
  10. 2-5 日本語環境構築 実行するコマンド sudo apt-get install fcitx-mozc sudo apt-get install

    fonts-noto 日本語フォントを持つIMEパッケージをインストール
  11. 2-8① ユーザー作成 新ユーザーのグループ構成を「pi」と同じにする グループ「pythoniot」を「pi」と同じ構成にするコマンド sudo usermod -aG adm,dialout,cdrom,sudo,audio,video,plugdev,games,users,input,netdev,gpio,i2c,spi pythoniot ユーザーpiのグループ構成を確認

    ユーザーpythoniotのグループ構成を確認⇒piと異なる sudo usermod –aG [piのグループ構成] [新グループ名]でpiと同じグループ構成になる pythoniotのグループ構成がpiのグループ構成と同じになっていることを確認
  12. 2-8① ユーザー作成 デフォルトのpiユーザーのユーザー名を変更(ここではoldpiにする) 参考URL: https://sekisuiseien.com/computer/11297/ SDカードはこの後の2-2➁の公開鍵は実装してない raspi-configを起動し、3.Boot Option⇒B1 Desktop /

    CLI ⇒B1 Consoleを選択して、一度rebootする Reboot後、以下のコマンドを実行してユーザ:piのユーザー名をoldpiに変更、ディレクトリ名もoldpiに変更 ユーザー名を「pi」⇒「oldpi」に変更 ディレクトリ名も「pi」⇒「oldpi」に変更 グループ名も「pi」⇒「oldpi」に変更 Whoコマンドを実行し ユーザーがpythoniotだけなのを確認 raspi-configで、B4 Desktop Autologinに戻しておく
  13. 2-8➁ 公開鍵認証(各自で設定) 公開鍵認証を許可し、rootログインとBASIC認証の許可を取消す .sshがすでにある場合は削除して再度作成 .sshにid_rsa.pubを配置 .sshを読込・書込・実行モードに設定 authorized_keysを読込・書込モードに設定 _configを全ユーザー読込・書込可能に設定 … …

    /etc/ssh/sshd_configの中身を3か所変更する rootログインができないようにする 公開鍵認証を許可する BASIC認証(パスワード認証)ができないようにする _configを自分だけが読込・書込可能に設定 sshを再起動 Ctrl-x、yで保存してnanoを終了 .sshがすでにある場合の削除コマンド sudo rm -r .ssh
  14. 2-9 iptables(LinuxのFW)の設定 IPv4のINPUTをローカルループ、MQTT、ssh、タイムサーバに限定する *filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0]

    :OUTPUT ACCEPT [0:0] -A INPUT -i lo -j ACCEPT -A INPUT -d 127.0.0.0/8 ! -i lo -j REJECT --reject-with icmp-port-unreachable -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT -A INPUT -p tcp -m tcp --dport 8883 -j ACCEPT # ポート番号は、/etc/ssh/sshd_config で設定したもの(5XXXX)と同じにする #-A INPUT -p tcp -m state --state NEW --dport 5XXXX –j ACCEPT -A INPUT –p tcp –m state –syn –state NEW –dport 5XXXX -m hashlimit --hashlimit-name t_sshd --hashlimit 1/m -- hashlimit-burst 10 --hashlimit-mode srcip --hashlimit-htable-expire 120000 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 123 -j ACCEPT -A INPUT -p udp -m state --state NEW -m udp --dport 123 -j ACCEPT -A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7 -A INPUT -j REJECT --reject-with icmp-port-unreachable -A FORWARD -j REJECT --reject-with icmp-port-unreachable -A OUTPUT -j ACCEPT COMMIT Ctrl-x、yで保存してnanoを終了 この内容に 書き換える
  15. 3-2 Hello world!(コメントとインデント) Pythonは インデント で文をグループ化するのが大きな特徴 #を書くと、それ以下の一行分はコメント文になる コメント文 インデントでループの階層を定義 (半角で4コマ)

    プリント文:print(xxx)で変数xxxを表示 print(“xxx”)で””で挟んだ文字列を表示 RaspberryPiのコマンドラインで 「python + ⏎」でpythonコマンドプロンプトが出る
  16. 3-3 数値型と文字列型 数値型: 整数 、浮動小数点数 、複素数 (浮動小数点数 は倍精度) 文字列の結合も +

    で可能 “ ”または‘ ’で括った文字を直接結合可能 文字列型: " "または' 'で括った文字 異なる型は結合できない これは可能
  17. 3-4 シーケンス型(list型、tuple型) list型: [ ]でくくる ,で区切る 文字列型でも数値型でも作れる 値の書き換えができる tuple型:,で区切るだけ 文字列型でも数値型でも作れる

    tuple型は 値の書き換えはできない tuple型を書き換える場合は 定義をしなおす list型はミュータブル、tuple型はイミュータブル、両方インデックスあり (参考)イミュータブル: https://python.ms/immutable
  18. 3-5 set型、マッピング型(dictionary) set型はdictionary型のkey部分だけのデータ型 set型はイミュータブルでインデックスが無い dictionary型のkeyはイミュータブルで重複不可、値はミュータブル set型: { }でくくる ,で区切る 文字列型でも数値型でも作れる

    インデックスが無い dictionary型:「key : 値」の組合せを{ }でくくる 「key : 値」の組合せは,で区切る 文字列型でも数値型でも作れる 値の書き換えができる set型はtuple型と同様に 値の書き換えはできない set型はtuple型と異なり 同じ値を複数カウントしない set型はtuple型と異なり データを順番付して保存できない ⇒インデックスがないから指定できない
  19. 3-6 制御フロー(if 文、elif、else、for文) ifステートメント: いわいるif文 else if はelifと記述する forステートメント: 「文字列」というlistに3つの文字列を値として入れる

    ⇒3つの値なのでインデックスは0,1,2 for文ではシーケンスのインデックス順にループを実行する ※他の言語にはないところで慣れが必要 for文を数値で制御するには組込み関数range()が必要 組込み関数len()を使うとlistのインデックス(要素)の総数が 得られる ⇒左の例でrange(len(文字列))はrange(3)と同義 else ifはelifと表記 for文は他言語と異なりシーケンスをイタレータにできる 慣れが必要
  20. 3-7 制御フロー(while文、continue、break) continue: ループの途中で ループの先頭に戻る break: ループの途中で ループから抜ける else節: if文以外でも

    for文、while文のendで 実行することがある whileステートメント: いわいるwhile文 条件が正である限り ループ内の処理を実行する Elseをfor文/while文のループ後に置くことがある
  21. 3-8① ライブラリー Python標準ライブラリ: https://docs.python.org/ja/3/library/index.html モジュール・パッケージ・ライブラリの関係 よく使うライブラリー 組込み型: int、float list、tuple、range set、dictionary

    組込み例外: KeyboardInterrupt EOFError、 ImportError FileNotFoundError ZeroDivisionError データ型: datetime ファイルアクセス: pathlib、os.path ファイルフォーマット: csv 汎用OS: os、io time 画像処理: openCV PIL(Pillow) 数値演算: numpy 機械学習: scikit-learn Pytorch TensorFlow TensorFlowフレームワーク: pandas keras 標準ライブラリー 外部ライブラリー ライブラリ: いくつかのパッケージをまとめたもの (モジュールやパッケージをライブラリと 呼ぶこともある) パッケージ: 複数モジュールをまとめたもの モジュール: pythonファイル(.py)のこと 複数のクラスや関数を含む 呼び出して使えるように、定型のpythonプログラムをまとめたもの
  22. 3-8② モジュール・クラス・メソッド 必要なモジュール(ライブラリ)をimportしてクラス、メソッドを呼び出す t0 = datetime.datetime.now() 新たに定義した datetimeクラスの インスタンス datetime

    モジュール モジュール内の クラス ローカルの現在時刻を 取得するメソッド ←ライブラリーをインポート ←モジュールの中のdatetimeクラスよりnow()メソッドで プログラム実行開始したローカル時間を取得 ←”d”が押されたら、開始時間から今までの経過時間を表示 ←”z”が押されたら終了 実行結果
  23. 3-9 関数 Pythonの特定の処理をひとまとまりにしたもの 引数と返り値を定義することができる 実行開始時刻からの時間差を表示するプログラム(引数なし・返り値なし) ←def 「関数名」() で関数を定義、行末は:が必要 ←関数の中身 ←上で定義した関数

    now() を実行 ←実行結果 ←ライブラリーをインポート ←モジュールの中のdatetimeクラスよりnow()メソッドで プログラム実行開始したローカル時間 t0 を取得 現在時刻とt0の時間差をprint 引数あり・返り値なしバージョン 引数あり・返り値ありバージョン ←引数で実行開始時刻を渡す ←引数で実行開始時刻を渡す 返り値で計算結果を返す deltaというインスタンスに 返り値を受け取る
  24. 3-13 nanoエディタでhello.pyをつくる nanoエディターで実行ファイルを作成し「Hello World」を表示する ここに、Hello Worldを表示するコードを書き込む 保存したファイルの実行結果を確認 sudo nano new_hello.py

    実行権限必要 nanoで エディターが 立ち上がる ファイル名(新規/既存いずれもOK) .pyの拡張子でpython fileと認識 「sudo python new_hello.py」で実行 Ctrl-x、yで保存してnanoを終了
  25. 3-14 GPIOで光センサーデータを読込む 光センサーボードをつないでデータを表示する (3)使用するライブラリー importするライブラリー wiringpi : as piとして読み込む、 GPIOの制御に使う

    time : サンプリング時間の制御に使う wiringpiから呼び出す関数 wiringpi.wiringPiSetupGpio() : GPIO初期化関数 wiringpi.pinMode(trigger_pin, PIN_MODE) :指定portの入出力モードを設定 trigger_pin :GPIOのport番号 PIN_MODE :入力値を読む時はpi.INPUT、出力時はpi.OUTPUT pi.digitalRead(trigger_pin) :指定portの入力信号を読み取る trigger_pin :GPIOのport番号 timeから呼び出す関数 time.sleep(sec) : sec秒だけプロセスを停止させる sec :停止させたい時間、単位は秒、1秒以下は少数を入力 ctrl-cをつかまえる組込み例外 KeyboardInterrupt
  26. 3-14 GPIOで光センサーデータを読込む 光センサーボードをつないでデータを表示する (5)関数定義・main文 ・今作ったファイルを別名保存する ・プログラムの処理部を3-9のように関数定義する ・__name__を使ったmain文を使った記述に書き直してみる __name__変数の使い方 def 「関数名」(引数):

    #処理内容 if __name__ == ‘__main__’: #処理部を記述 #ここに関数を呼び出す … __name__を使わないモジュール __name__を使ったモジュール importすると 実行される importしても 実行されない https://blog.pyq.jp/entry/Python_kaiketsu_180207 https://techacademy.jp/magazine/18871 https://qiita.com/ryo_xsjsj/items/c0b64f3679da9d168aaa 参考:
  27. 4-1 クラウド接続準備(aws:ログイン) awsにログインしてIoT core※のマネジメントコンソールを開く (※IoT向けサービスの統合機能) ログインURL(下ページが開く): https://447139383727.signin.aws.amazon.com/console アカウント:447139383727 ユーザー名:HAMAKITA_Python パスワード:hamakitaAIIoT

    ←検索窓に「IoT」と入力 ←「IoT core」をクリック マネジメントコンソールよりIoT coreを選択 IoT coreに入ったらリージョンを東京に変更 「開始方法」をクリックして利用開始 (2回目以降はこのページ↓は出ない)
  28. 4-1 クラウド接続の準備(aws:ポリシー作成) ポリシーを作成する(初回または変更したい時だけ) 名前: 任意のポリシー名 アクション: iot* リソースARN: * 許可:

    チェックを入れる マネジメントコンソールより安全性を選択 ポリシーを選択 ポリシーの作成 項目を入力して「作成」
  29. 4-2 MQTTで双方向通信(MQTTとは) Brokerを介してトピック指定による多対多の非同期通信をする オーバーヘッドはHTTPSの1/10 開発経緯 ・1990 年代後半に IBM が考案したプロトコル ・油田パイプラインでセンサーを衛星のリンクに開発

    特徴 ・非常に軽量でHTTPSの1/10のオーバーヘッドで済む ・publish/subscribe型のメッセージ転送 ・IoT/モバイルに適する (Facebook Messenger等で利用) HTTP MQTT 同期/非同期 同期 非同期 送受信対象 1対1 多対多 データ量 大きい(重い) 小さい(軽い) 通信が不安定 ×(送受信不可) ◦(再送受信可能) Broker IoT sensor IoT sensor IoT action pub topic AWS IoT Core sub topic pub topic sub topic pub topic sub topic pub topic Device gateway Device gateway Device gateway Paho-mqtt python ドキュメント:https://pypi.org/project/paho-mqtt/ https://www.eclipse.org/paho/clients/python/docs/#connect-reconnect-disconnect
  30. 4-3 クラウドでデータ表示 DHT11温湿度センサーをラズパイに接続 ラズパイのpub用codeの準備とクラウドで表示する環境を構築 温湿度センサー (DHT11) ※GNDはどこでもOK AWS IoT Core

    IoT rule Role Amazon CloudWatch データHUB 権限設定 実行 ルール 表示 Endpoints CA署名 認証EP データをpub ①pub用code ➁クラウド側環境 接続
  31. 4-3 クラウドでデータ表示(➁クラウド側環境) IoT ruleの作成➂ Topic名 本番環境を想定して deviceのtempにする None 表示したい値:temp Topic名

    メトリクス名、名前空間、値は、それぞれがラズパイからtopicにpublishされた右の値になる
  32. END