OmniAICreator/Qiita-1.07M huggingface dataset:
初めてのPython 開発環境を用意する

診療放射線技師、医学物理士をやっている者です。
プログラミングを学習していく過程を備忘録として記事に残していきます。
今後誰かの参考になれば幸いです。


スキルとして漠然とプログラミングを始めたくて、最初に手をつけたのがProgateでした。
ホリエモンがオススメしていた影響です。
いろんな言語のチュートリアルを一通りクリアして、Pythonをメインに勉強することにしました。
Web、アプリ、データ分析など汎用的に使えそうで、人口も多そうだったのと、
仕事柄機械学習が研究テーマとしてホットだったことが決め手です。

今回は、実際に自分のPCでPythonを動かしたはじめの一歩についてです。


# 全ては環境構築から
###PCを用意
Pythonを扱っていくにあたり、まずは自分のPC上でPythonを動かす環境を用意する必要があります。
（※私はMacユーザーです。）

<必要なもの>
・PC

高いPCは（とりあえずは）必要ないようです。
PC一つでプログラミングを始められるのは、敷居が低くてありがたいです。


###Anacondaをインストール
手元にPCを用意できれば、次にPythonをインストールします。
と言っても、実はMacにはPythonが標準搭載されている、らしい。
インストールしなくても使えないことはないのですが、バージョンが古いもののようなので、最新のバージョンをインストールしたいところです。（やりたい処理によってはバージョン2.7（2系）の方が適切である場合もあります。初心者はとりあえずバージョン3.７(3系)をインストールしてしまって問題ないと考えています。）

Pythonをインストールする方法がいくつかある中で、私は定番のAnacondaを使いました。
AnacondaにはPython本体の他に、機械学習においてよく使われるライブラリ等もセットで入っており、よく分からない初心者でもとりあえずこれさえあれば始められます。

「Python欲張りセット」と言ったところでしょうか。

以下のURLから無料で簡単にAnacondaをダウンロードできます。
https://www.anaconda.com/distribution/

<img width="986" alt="スクリーンショット 2020-01-24 20.06.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570980/6d7ac993-e5be-162e-3fb7-a20eade9eb4b.png">

手順に従ってAnacondaのインストーラーのダウンロード、
Anacondaのインストールを行います。


###動作確認
インストールが完了すると、PATHも通り、すぐに使える状態だと思います。
（※Mac OSのバージョンによっては、自分でPATHを追加する必要があります！）

Finderからターミナルを起動し、動作確認をしてみます。
<img width="799" alt="スクリーンショット 2020-01-24 20.53.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570980/b2962502-ceb8-43ea-6d67-b299747b6786.png">

ターミナルを起動できたら、以下を打ち込んでEnterを押します（コマンドを実行）。

```Terminal
python　--version
```
"Python 3.7.4" と表示されます。

次は、

```Terminal
conda --version
```
"conda 4.7.11"と表示されます。
問題なく動作しています。








さらに詳しいAnacondaのインストール方法は、ネット上で優しい方々がたくさん共有してくれています。
またターミナルの使い方も勉強しておくと後々困らないです。



#初めてのPythonファイルを実行
早速Pythonデビューしてみます。
標準ソフトでも構いませんので、適当なテキストエディタで次のコードを入力し、"hello.py"という名前でデスクトップに保存します。(私は"Atom"というテキストエディタを使っています)
".py"というのがPythonファイルの拡張子です。

```python:hello.py
print("Hello")
```

次にPythonファイルを実行してみます。実行にはターミナルを使用します。
ファイルを実行するには、ターミナル上でそのファイルが存在するディレクトリに移動する必要があります。
今回の場合はデスクトップに保存したので、デスクトップに移動すれば実行できます。
あるフォルダ内にファイルを保存したなら、そのフォルダに移動する必要があります。
ターミナルを起動すると、ホームディレクトリにいる状態からスタートです。
通常、デスクトップはホームディレクトリの直下にあるので、次のコマンドを実行してデスクトップに移動できるはずです。

```Terminal
cd desktop
```
デスクトップにある"Test"というフォルダに移動したい場合は

```Terminal
cd desktop/Test
```

で移動できます。
ひとつ前のディレクトリ（親ディレクトリ）に戻りたいときは、

```Terminal
cd ..
```

で戻れます。"cd"の後ろのスペースを忘れないように。
正しくディレクトリに移動できたら、実行あるのみです。
次のコマンドを実行します。

```Terminal
Python hello.py
```

ターミナル上に"Hello"と表示されれば成功です。
"Python ファイル名"と打ち込んでEnterを押すことでPythonファイルを実行できます。
無事に自分のPCでPythonを動かす環境を構築できました。
php 三項演算子

# 三項演算子

if文をすっきり書けるので便利ですよね。
実装してて気になったので、備忘録をかねて

# ①基本

```
条件式 ? 式1 : 式2
```

```
$lang = 'En';

$lang == 'Jp'  ? $msg = 'こんにちは' : $msg = 'Hello';
print $msg;
'Hello'
```

# ②代入+基本
```
代入式 + 条件式 ? 式1 式2;
```
```
$lang = 'Jp';

$msg = $lang == 'Jp'  ? 'こんにちは' : 'Hello';
print $msg;
'こんにちは'
```

これなら式1、式2にそれぞれに式を書く手間が省ける

今まで①パターンで書いてたけど、次からは②のパターンを使用してみようっと
なにかの参考になれば、幸いです。
GoのサンプルWebアプリをローカルで実行した時にはまったことのメモ

# 背景
- [Goプログラミング実践入門](https://book.impress.co.jp/books/1115101145)に記載されている[サンプルWebアプリのコード](https://github.com/mushahiroyuki/gowebprog)をローカルで実行しようとしたときにはまったことのメモ

# やっていたこと
- ホームディレクトリに`git clone`してそのまま`go build`をした
- すると以下のエラーが

```
route_main.go:5:2: cannot find package "chitchat/data" in any of:
	/usr/local/Cellar/go/1.13.4/libexec/src/chitchat/data (from $GOROOT)
	/Users/XXXXXX/go/src/chitchat/data (from $GOPATH)
```
- route_main.goを見てみると、importで自プロジェクトのパッケージを呼び出しており、そこが悪さをしていそう

```go
import (
	"github.com/mushahiroyuki/gowebprog/ch02/chitchat/data"
)
```

# 解決策
- 今回のように、単純に動かすだけなら`go get`コマンドでソースを取得すれば良い

```
$ go get github.com/mushahiroyuki/gowebprog/ch02/chitchat/data
```
- `go get`コマンドによって、以下の処理が行われる
    - `$GOPATH/bin`に実行ファイルが置かれる
    - `$GOPATH/src`にパッケージのソースコードが置かれる
        - `$GOPATH/src/github.com/mushahiroyuki/gowebprog/ch02/chitchat`というパスに置かれる


- 実行するだけなら、`$GOPATH/bin`配下に取得された実行ファイルを起動させればよい
    - つまり、**自分でbuildする必要がなかった**
- ソースを変更しても、`go build`で新しい実行ファイルが生成されるので問題なさそう

# なぜエラーになっていたのか
- 実行できるにしても最初に発生していたエラーは何なのか
- それは、importに指定する`github.com/mushahiroyuki/...`というパスは、`$GOPATH/src`からのパスに対応しているため
- `go get`でソースを取得すると、`$GOPATH/src`配下に作成されるパスがimportに記載したパスと一致することになる
    - importへの記載は[公式ドキュメント](https://golang.org/cmd/go/#hdr-Remote_import_paths)に書かれているように、同じプロジェクト内であっても`github.com/...`という絶対パスでの書き方が推奨されている
- 何も考えずに`git clone`でローカルに落としてくると、importに記載したパスに合わないため、パッケージが見つからずエラーになる

# Gitで管理したい場合はどうするのか
- 個人的にローカルで実行させるだけなら上記の方法で問題無いが、チームで開発するなどの理由でGitで管理したい場合はどうするのか
- 正解は無さそうだが、以下の2パターンがありそう
    - importのパスに合うように`git clone`する
    - 大元のリポジトリをforkし、`go get`で取得したパスに`git remote add`でforkしたリポジトリへの参照を追加
        - fork先へプッシュし、originへのプルリクエストを作成する

# 参考
- [他言語から来た人がGoを使い始めてすぐハマったこととその答え](https://qiita.com/mumoshu/items/0d2f2a13c6e9fc8da2a4)
- [github でホストされている go アプリを fork して PR する時には、まず go get から始めよう](https://qiita.com/t-suwa/items/d384facb79866dc16cad)
- [【Go言語】パッケージのimportについて整理した](https://qiita.com/ogady/items/0cedd3599c4dc13e9a95)
業務、機能、処理ってなに？　　　　　　（本当は抽象化と哲学の話）

# はじめに
　開発に携わる人には聞きなれた言葉、**「業務」**、**「機能」**、**「処理」**
　でも、全員が同じ意味でとらえているでしょうか？
　普通に使っている言葉なのに微妙にニュアンスが違っていませんか？

　結局は決め事なので、ステークホルダ間で定義すればよいことですが・・
　今回は、ちょっと違った視点で三つの言葉の役割を考えてみました。


### 業務
　ユーザ（利用者）の世界に一番近い概念
　**現実社会**のルールが適用される領域

### 処理
　**コンピュータの世界**に一番近い概念
　プログラムロジックのルールが適用される領域

### 機能
　業務と処理はそれぞれ独自の世界を持っていますが・・
　では、機能って何でしょう？
　一番わかりやすい表現では、業務と処理をつなぐもの
　現実社会とコンピュータの世界をつなぐもの

　ということで、今回はこの**機能**について少し掘り下げてゆきたいと思います。

### 業務分析
　実際の開発で行う業務分析は、現実社会を「データ」や「処理」といった**物差し**で切り取ってコンピュータの世界に**投影**することなので、機能という概念はここでは必要無いように思えます。

### 業務の特徴
　現実の世界は様々な要因が絡み合って非常にカオスな世界で、常に変化し続ける特徴を持っています。
　そんな複雑で、不安定な世界をそのままコンピュータの中に持ってくるのは大変です。
　その点、コンピュータの世界は論理的な秩序ある世界でなければなりません。
　AIの進歩でかなりカオスも取り込めるようになっていますが、それでも人間が期待する答えを毎回ぶれることなく出し続けるには正しくルールをロジックとして、プログラミングしなければなりません。

### 機能の役割
　そんなわけで、機能の出番が来るわけです。
　カオスな世界から不要な条件を間引き、実現したい業務だけを世界の一部分として切り取り、処理との間のバッファーの役割を果たす。

### 処理の役割の再定義
　せっかく機能がカオスな世界から秩序ある世界へのバッファーとなって頑張ってくれるので、処理としてはシンプルなことだけ引き受けることを心掛け、複雑さをできるだけ排除します。
　処理が単純になればそれだけ使いまわしができるようになります。
　出来上がったビーフシチューを肉じゃがにするにはちょっと無理がありますが、単純に下処理した牛肉、玉ねぎだったらどっちにも使いまわしができるようになります。
　単体試験もすごく単純になり、開発時間や費用の削減につながりますね。


# ということで抽象化の話
　機能の役割の中で
　”カオスな世界から不要な条件を間引き、実現したい業務だけを世界の一部分として切り取り”
　という表現がありましたが、じつはこれをIT業界の専門用語では「抽象化」と表現しています。

　ここからは、いろいろな視点から抽象化の話をします。

### 構造化設計の抽象化
　まずは基本的な構造化設計から
　構造化技法での抽象化はモデル化の中で実現されていて、次のような流れで行われます。
（１）現行物理モデル
（２）現行論理モデル
（３）新論理モデル
（４）新物理モデル
　ここで、（２）と（３）の論理モデルが抽象化の工程となります。
　つまり、同じ人間という実体がAさん、Bさんというように個々に表現された物理モデルから
　AさんもBさんも人間だ！　というようにひとくくりにして「人間」として表現するのが論理モデルです。
　このことにより、分かりづらい物理モデルから余計な要素を省き理解しやすい形へ表現することで、現行の改善点、問題点が明確になります。

### オブジェクト指向の抽象化
　オブジェクト指向で、物理モデルに相当するのが、オブジェクト図です。
　AさんオブジェクトもBさんオブジェクトもしっかり表現されます。
　論理モデルに相当するのが、クラス図です。
　AさんオブジェクトもBさんオブジェクトも一つの人間クラスとして表現されます。

### 機能は・・・
　ということで、機能も抽象化という役割を担っているという話がしたかったのが今回の肝でした。
　業務という物理モデルを機能で抽象化し、理解しやすい形で表現する。
　という機能の役割を意識して開発してゆきましょう！

## 最後に
　皆さんへ問いかけ
　業務を「目的」、処理を「手段」と見ることもできますが、そうすると機能ってなんでしょう？

　こうしてみると、システム工学って哲学だと思いませんか・・
pip のインストール

あまり自分で入れる事も無い気がしますが、仕事で centos7 で開発環境作った時に入ってなかったのでメモです。

```
$ python --version
Python 2.7.5
```

のような環境です。

```
$ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
$ python get-pip.py
$ pip --version
pip 20.0.2
```
以上。

https://pip.pypa.io/en/stable/installing/
ruby,railsの特徴

# ruby
- スクリプト言語である。

プログラミング言語にはスクリプト言語、コンパイラ言語と言われる言語があり、
人間が書いたコードを機械が実行するには翻訳を行う必要がある。
コンパイラ言語は事前に翻訳し、スクリプト言語は随時コンパイル（翻訳）しつつ実行される。
スクリプト言語であるrubyは翻訳する必要がないため開発しやすい反面、実行速度が遅めである。

- オブジェクト指向である。

最初からオブジェクト指向の言語として開発されたため、
変更に強く、再利用しやすいコードを書きやすくなっている。

上記の理由から記述量が少なく済んだり、コンパイルする必要がないため生産性が高い。
そのため、フレームワークであるrailsと合わせて短期間で開発を進める必要があるスタートアップ企業などで好まれて使用されやすい。


# rails

- 言語としてrubyを使用しているため、比較的習得しやすい。

- 習得したスキルを幅広く使用できる。
rubyを取得してしまえばフレームワークはrailsほぼ一択になるため幅広く活用することが出来る。

- 開発を効率化する仕組みが多数用意されているため生産性が高い。
rails newでアプリの雛形を作成することができたり、ActiveRecordによってSQL操作ができるなど、
開発効率を高める仕組みが多数用意されている。
DBpediaを使って、検索語からデータ取得

##環境
python3

##準備
まず、DBpediaからデータ取得を簡単にしてくれるライブラリを持ってくる

```
pip install sparqlwrapper
```

## 取得したいデータを決める
まず、DBpediaのページから、決定する。
http://ja.dbpedia.org/page/%E4%B8%AD%E4%BA%8C%E7%97%85%E3%81%A7%E3%82%82%E6%81%8B%E3%81%8C%E3%81%97%E3%81%9F%E3%81%84!

URLで、「http://ja.dbpedia.org/page/{検索語}」
って感じで、
指定する。なお、大文字小文字も区別されるので、注意。
例えば、akb48はヒットしないが、AKB48はヒットする。
なので、wikipedia本家から実際に検索してみて、検索語を確認すれば良い。<img width="1439" alt="スクリーンショット 2020-02-11 17.44.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179803/484dcd40-8daa-b104-a695-a4d0b165350e.png">


## プログラム
取得したいデータを指定する際には、
DBpediaに「dbpedia-owl:abstract」みたいに書いてあるものを
追加していくことになる。
その場合は、select文の「?a」みたいに任意の名前を追加していって、
whereの中でタグを追加していく。
なお、追加するたびに、セミコロンは忘れてはいけない。

```python:nogizaka-suko.py
# -*- coding: utf-8 -*-
from SPARQLWrapper import SPARQLWrapper

sparql = SPARQLWrapper(endpoint='http://ja.dbpedia.org/sparql', returnFormat='json')
sparql.setQuery("""                                                                                                                                                                      
    PREFIX dbpedia-owl:  <http://dbpedia.org/ontology/>                                                                                                                                  
    SELECT ?a ?b ?o WHERE {                                                                                                                                                                 
<http://ja.dbpedia.org/resource/中二病でも恋がしたい!> rdfs:label ?label;
<http://dbpedia.org/ontology/director> ?a ;
<http://dbpedia.org/ontology/productionCompany> ?b ;
<http://dbpedia.org/ontology/abstract> ?o .
     }                                                                                                                    
""")
results = sparql.query().convert()


print(results)


```

## 取得結果
こんな感じで、タイトルも概要も取得できる。
<img width="718" alt="スクリーンショット 2020-02-11 17.39.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179803/c6a0d578-9307-d5e5-1e83-4030c557aa93.png">


## 感想
dbPediaは大学生の時授業内でやったことあったけど、めっちゃ前だったので使い方とかほとんど忘れていた。
しかもあの時はPHPでやっていたので、今回pythonでやってみたらうまくいったので嬉しい。

あと、直接HTMLのタグを指定してwikipediaからスクレイピングするなんてナンセンス！DBpedia使いましょうねみたいな記事を見たことあるけど、
DBpediaだけじゃ全てのデータを取得できるわけではなさそうなので、
結局はHTMLのpタグの要素を動的に取得したりするみたいな処理をやる必要がありそう。
プロセスビルダーとFlowBuilderを組み合わせた（応用）

#はじめに・作業の流れ
こちらは前回書いた記事の「[プロセスビルダーとFlowBuilderを組み合わせた(基礎)](https://qiita.com/DEKA_PIYO/items/b5e0018336761befe8bd)」の続編となります。
内容が連続しているわけではないのでこちらだけ読んでも差し支えないですが、そもそもFlowBuilderがよくわからない人は最初に読まれたほうが良いかもしれません。

今回は一括処理を行うための「ループ」について解説していきます。そしてそれに関連して「レコードコレクション変数」と「ループ変数」についても説明していきます。

##「コレクション変数」とは
一つのデータを入れる箱が変数といいますが、複数のデータを入れる箱は「コレクション変数」といいます。正確かどうかはっきりしませんが、一言でいうと配列とかリストというとしっくりくるかもしれません。

![テキスト型のコレクション変数.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510376/e5e04090-e2ec-2e7c-f976-3b4b2264f691.png)


イメージでいうと上の図の通りです。
フローでコレクション変数を作成するにはデータ型のとなりにあるチェックボックス「複数の値を許可 (コレクション)」にチェックを入れるだけです。

コレクション変数の中でも特にレコード情報を保存した複数のデータを「レコードコレクション変数」といいます。

![レコードコレクション変数.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510376/c52b5d8d-638a-916e-1b3b-f6b8b037ae49.png)

イメージは上記のようになります。複数のレコードがコレクション変数に収められており、各々のレコードの情報も持つことが出来ます(厳密には少し違うのかもしれません。。。)。

##「ループ」を使用するためには
ポイントは**レコードコレクション変数単体では各々のレコードの操作が出来ない**ということです。このレコードを編集するには「ループ」を使用して**レコードコレクション変数からレコードの情報を「ループ変数」に渡すことが必要**になります。

![フローのループ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510376/792c992f-8053-bb96-c36d-c04aa1931c95.png)

「ループ」を使用するとどのコレクション変数をループさせるか、ループするためのループ変数を指定する必要があります。ループ変数はレコード変数と同じ設定で出来るのですが、特にループで使用するレコード変数をループ変数というようです。

##例：商談の一括更新のループを作成する
今回は同じ取引内にあるすべての商談のフェーズを「Close Won」にするというフローを作成してみたいと思います。

まず全体像は以下の通りになります。

![商談一括更新.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510376/17f4f86c-0d07-5f8e-c960-810c20ea6d81.png)

###レコードの取得
一番初めのレコードの取得は動的にレコードを取得したいので前回解説した基礎のように条件を指定していきます。「変数に保存する商談項目を選択」では商談ID以外にもフローで使用する項目を指定することができます(Spring'20ではそれすら自動的にすべて使えるようになるそうです・・・)。今回使用する項目は「取引先 ID」「フェーズ」です。

次のレコード取得は最初に取得した商談の取引先IDに一致するものを全て取得します。

![取引先に関連する全ての商談レコード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510376/0e541520-3d2d-cc78-7079-c753ad3f6a72.png)

「商談レコードを絞り込み」の値には「get_Opp.AccountId」とありますが、意味合いとしてレコード変数「get_Opp」の取引先IDを指定していることになります。このようにレコード変数はそれぞれレコードの項目を持つことが出来て、それを指定して値や条件として使えるので便利です。

また今回は条件に合致するすべてのものを保存してループで使用するので「保存するレコード数」はすべてのレコードを選択します。

###ループの設定

上記のループの画像で説明したとおりの設定となります。

![ループの設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510376/c6797dd7-a726-2b9f-6dfa-54172b0ec929.png)

ループ変数の内容としてデータ型を「レコード」、コレクション変数と同じオブジェクト（今回は商談）でなければ上手くいきませんのでご注意ください。

###レコードの更新
こちらもループの画像で意味合いの記載はあります。
ループ中の商談IDと一致するものに対して、フェーズを最初に取得した商談と同じフェーズにするということになります。

![レコードの更新（ループ）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510376/9d2cfe82-cf99-34b8-a232-5801fe3592ae.png)

###プロセスビルダーの設定
こちらのフローを保存し、有効化したのち、プロセスビルダーで商談が「Close Won」になったらこのフローが起動するアクションを設定、そしてフロー変数と商談IDを指定してあげれば完成となります。

#あとがき
フローのループが理解できるとあれもこれも簡単に一括でレコードの更新ができるようになり、フローを作るのが楽しくなってくると思います。自分の組織の課題に合わせた設定も少しずつフローで出来るようになるかと思います。ぜひ楽しみながらFlowBuilderを操作してフローを作ってみてください！

長文最後まで読んでいただきありがとうございました！

##ループの修正版
こちらを記事にした当時はこのループが正しいものだと思っておりましたが、厳密にはこの方法だと制限に達してしまい上手くいかないケースも出てくるのではないかと思います。上記のループを修正した記事がこちらになります。

[フロービルダーで制限に達しないようにループを使ってみた](https://qiita.com/DEKA_PIYO/items/b08695a855700888680d)
Julia Install 方法

# Julia Install
Juliaの記事を読んだので早速環境構築してみた.BLASの設定のとこが分からないのでわかったら追記する.
### Linux系
```
git clone https://github.com/JuliaLang/julia.git
```

```
cd julia
```

```

git checkout (好きなversion)` ex): `git checkout v1.3.1
```

```
make -j4
```

終わり.インストールされたか確認

```
./julia --version
```

>$ ./julia --version
>
>julia version 1.3.1

```
./julia 
```
<img width="1437" alt="julia.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258554/52a09072-b5a3-a82c-e7fa-18872bc920ff.png">

できてる.

##公式
https://julialang.org/
【Python】mp3データをFFTする方法


#0. 概要
Pythonを使って、mp3データをFFTする方法です。ライブラリとしてpydubやffmpegを使うので予めダウンロードしてくださいね。

#1. ライブラリのダウンロード
```
sudo apt install ffmpeg
pip install pydub
```

#2. コード

```FFT.py
#! /usr/bin/env python
# -*- coding: utf-8 -*-
from pydub import AudioSegment as AS
import ffmpeg
import numpy as np
import matplotlib.pyplot as plt

file = "ファイル名を入れてね"

sound = AS.from_file(file + ".mp3", "mp3")
data = np.array(sound.get_array_of_samples())
spec = np.fft.fft(data)   #2次元配列(実部，虚部)
freq = np.fft.fftfreq(data.shape[0], 1.0/sound.frame_rate) 
spec = spec[:int(spec.shape[0]/2 + 1)]    #周波数がマイナスになるスペクトル要素の削除
freq = freq[:int(freq.shape[0]/2 + 1)]    #周波数がマイナスになる周波数要素の削除
max_spec=max(np.abs(spec))    #最大音圧を取得(音圧を正規化するために使用）
plt.plot(freq, np.abs(spec)/max_spec)

plt.grid()
plt.xlim([0,4000])    #グラフに出力する周波数の範囲[Hz]
plt.xlabel("Frequency[Hz]")
plt.ylabel("Sound Pressure[-]")
#plt.yscale("log")
plt.savefig(file + ".png")  #pngファイルで出力

```

#3. 補足
plt.yscale("log")のコメントアウトを外せばlogスケールに変更できます。
もしも ELB-HealthChecker で(あ|なか)ったら

## もしも ELB-HealthChecker であったら

Basic 認証の対象外にする

```apache:.htaccess
AuthUserFile /path/to/.htpasswd
AuthGroupFile /dev/null
AuthName "Input ID and Password."
AuthType Basic
require valid-user

Satisfy Any
Order Deny,Allow

SetEnvIf User-Agent "^ELB-HealthChecker.*$" hc
Allow from env=hc
Deny from all
```

## もしも ELB-HealthChecker でなかったら

https://example.com にリダイレクトさせる

```apache
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} !^ELB-HealthChecker.*$                                                                                                                       
RewriteRule ^.*$ https://example.com [R=301,L]
```
Nuxtで<component>のコンパイルが通らないときの解決法（eslintエラー）


## やりたいこと
Nuxtで、ヘッダーのロゴを囲うタグをTOPと下層で動的に変更したい。（わりとよくある）

- TOPページでは`<h1>~</h1>`で囲む
- 下層ページでは`<p>~</p>`で囲む

## コード

https://jp.vuejs.org/v2/guide/components-dynamic-async.html
https://papadays.com/post/4qivkrf9bpislqmnegobdy/

このあたりを参考に、`<component :is="">`を使って記述。

```vue:PROJECT/headerLogo.vue
<template>
  <NuxtLink
    to="/"
    class="headerLogo"
  >
    <component
      :is="tagName"
      class="headerLogo__inner"
    >
      <img
        src="@/assets/img/common/logo.svg"
        alt="ロゴ"
        class="headerLogo__img"
      >
      <span class="headerLogo__copy">ロゴコピー</span>
    </component>
  </NuxtLink>
</template>

<script>
export default {
  computed: {
    tagName () {
      if (this.$route.name === 'index') {
        return 'h1'
      }
      return 'p'
    }
  }
}
</script>
```

ごきげん束の間、何やらeslintのエラーでコンパイル通ってない。


## エラー
#### 内容

```
Expected '<component>' elements to have 'v-bind:is' attribute  vue/require-component-is
```

いやいや、`v-bind:is`（＝`:is`）書いてるんですけどもー・・・。

#### 原因

どうやらこれっぽい。
https://github.com/nuxt/eslint-plugin-nuxt/issues/65

プラグインのモジュールのバージョンによるバグ。
[スレッドの最下部コメント](https://github.com/nuxt/eslint-plugin-nuxt/issues/65#issuecomment-557918009)見ると、@nuxtjs/eslint-configで修正されてそう。
> eslint-plugin-vue@5 issue will be fixed in next release of https://github.com/nuxt/eslint-config


## 解決法
@nuxtjs/eslint-configを最新版にアップデートする。


#### 確認
package.jsonに[npm-check-updates](https://www.npmjs.com/package/npm-check-updates)かけてみる。

```
@nuxtjs/eslint-config           ^1.0.1  →   ^2.0.2
```

<b>わー。（見事に古い）</b>

このプロジェクトは2ヶ月程前に、[公式](https://ja.nuxtjs.org/guide/installation)にある`yarn create nuxt-app`でプロジェクト作成している。
当時の配信版では@nuxtjs/eslint-config`^1.0.1`だったけど今（20/02/11時点）は`^2.0.2`になってる。
ちなみに、Nuxt自体も最新だと`2.11.x`が出ているけども、nuxt-appだと`^2.0.0`。

下手にアップデートして動かなくなったら嫌なので、
念の為、最新版nuxt-appで作られる空プロジェクトのpackage.jsonの中身確認してみる。

```json:test/package.json
{
　 〜略〜
  "dependencies": {
    "nuxt": "^2.0.0"
  },
  "devDependencies": {
    "@nuxtjs/eslint-config": "^2.0.0",
    "@nuxtjs/eslint-module": "^1.0.0",
    "babel-eslint": "^10.0.1",
    "eslint": "^6.1.0",
    "eslint-plugin-nuxt": ">=0.4.2"
  }
}
``` 
`"@nuxtjs/eslint-config": "^2.0.0"` になってた。
（`"nuxt": "^2.0.0"` のままだけども）

というわけで、Nuxtは2.0.0のまま、@nuxtjs/eslint-configあげても大丈夫そう。

#### パッケージ更新

1回消して再インストール。

```
yarn remove @nuxtjs/eslint-config
```
```
yarn add @nuxtjs/eslint-config --dev
```
```json:PROJECT/package.json
{
  〜略〜
  "devDependencies": {
    "@nuxtjs/eslint-config": "^2.0.2",
    "@nuxtjs/eslint-module": "^1.0.0",
    ︙
  }
}

```

更新完了

実行してみると、他でこけるところも特になく、無事冒頭のコードでコンパイルできました！
めでたしめでたし👏
Zephyr > debug > printk()出力をファイル保存する > screen -L

```txt:動作環境
Ubuntu 18.04 LTS
ボード: STM32L476 Nucleo_64 (以下、STM32L476)
Zephyr 2.1.0-rc1
RTC: RX-8025NB
ロジック確認: Analog Discovery 2 (AD2)
```

### 概要

- RX-8025NBのI2C通信を実装中
- Hour, minutes, secondsの読み取りは実装した
- Hourの値が意図したものとは違う

### printk()のロギング

Hourの値を理解するために、printk()出力をファイルに保存する。
screenで表示される出力をファイル保存できればいい。 

下記を見つけた。

- [Save “screen” (program) output to a file](https://stackoverflow.com/questions/14208001/save-screen-program-output-to-a-file)

実際に-L付きでscreenを実行したところ、`screenlog.0`というファイルが生成され、screenの表示内容が保存されるようになった。
Chrome version 80 以降 grid-layout の 1fr の挙動が変わります

### TL;DR
Chrome 80 以降は grid 項目に最小値が設定されていないと、表示崩れが発生する場合があります。
具体的には grid-template-columns 等に 1fr を指定している箇所が影響します。

回避方法: 下記のように、minmax を用いて最小値を設定してください

Before

```javascript

grid-template-columns: 1fr auto 1fr;
```

After

```javascript
grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
```

### 参考サイト
詳細はこちらで
https://codepen.io/MadeByMike/full/LYVYXbv
Homebrew でインストールした JupyterLab で pandas がインポートできない

## 症状

Code セル

```py
import pandas as pd
```

実行結果

```py
ModuleNotFoundError                       Traceback (most recent call last)
<ipython-input-2-ca154c91f1ef> in <module>
----> 1 import pandas as pd
      2 

ModuleNotFoundError: No module named 'pandas'
```

## 調査

### JupyterLab のパスを調べる

Code セル

```py
import sys
import pprint

pprint.pprint(sys.path)
```

実行結果

```
['/Users/oppara/sandbox/jupterlab',
 '/usr/local/Cellar/jupyterlab/1.2.4/libexec/lib/python37.zip',
 '/usr/local/Cellar/jupyterlab/1.2.4/libexec/lib/python3.7',
 '/usr/local/Cellar/jupyterlab/1.2.4/libexec/lib/python3.7/lib-dynload',
 '/usr/local/opt/python/Frameworks/Python.framework/Versions/3.7/lib/python3.7',
 '',
 '/usr/local/Cellar/jupyterlab/1.2.4/libexec/lib/python3.7/site-packages',
 '/usr/local/Cellar/jupyterlab/1.2.4/libexec/lib/python3.7/site-packages/IPython/extensions',
 '/Users/oppara/.ipython']
```

### pandas のパスを確認

```sh
% pip3 show pandas
Name: pandas
Version: 1.0.1
Summary: Powerful data structures for data analysis, time series, and statistics
Home-page: https://pandas.pydata.org
Author: None
Author-email: None
License: BSD
Location: /usr/local/lib/python3.7/site-packages
Requires: numpy, pytz, python-dateutil
Required-by: 
```
## 原因

pandas がインストールされているパスが、JupyterLab のパスに含まれていない。

## 力技な対応

Code セル

```py
import sys
sys.path.append('/usr/local/lib/python3.7/site-packages')

import pandas as pd
```

## その他の対応

Homebrew でなく、pip(pip3) でインストールした JupyterLab を使う

```sh
% brew uninstall jupyterlab
% pip3 install jupyterlab
```

pip でインストールした JupyterLab のパス

```
['/Users/oppara/sandbox/jupterlab',
 '/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python37.zip',
 '/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7',
 '/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/lib-dynload',
 '',
 '/Users/oppara/Library/Python/3.7/lib/python/site-packages',
 '/usr/local/lib/python3.7/site-packages',
 '/usr/local/Cellar/protobuf/3.11.3/libexec/lib/python3.7/site-packages',
 '/usr/local/lib/python3.7/site-packages/IPython/extensions',
 '/Users/oppara/.ipython']
```


## 環境

```sh
% sw_vers
ProductName:    Mac OS X
ProductVersion: 10.15.3
BuildVersion:   19D7

% brew --version
Homebrew 2.2.5

% python3 -V
Python 3.7.6
```

## 参照

[Jupyter Notebook: ModuleNotFoundError: No module named &#39;pandas&#39; - Qiita](https://qiita.com/suin/items/655dea9bb2c876165807)
AWSクラウドプラクティショナーを受験しました。

#目次
　1.試験勉強
　2.模擬試験
　3.本番試験
　4.感想・結果

#1.試験勉強
　1.AWS認定クラウドプラクティショナー(トレノケート株式会社)を読む
　2.公式の模擬試験の実施
　3.AWS認定ソリューションアーキテクト(リックテレコム株式会社)を読む
　4.AWSの動画コンテンツとホワイトペーパーを読む
　合計 約20時間

#2.模擬試験
　まず一通り、クラウドプラクティショナー対策本を読み覚えたので模擬試験を受けてみました。
　ほかの方の記事を読むとそこまで難しい試験ではなさそうだし大丈夫だろうと思ったら**正解率50%でダメした。**
　**慢心ダメゼッタイ**
　
　これはあかんなと思い本試験の日程を変更(2回までは日程を変更できる様です)
　1冊では試験範囲をカバーできないため、
  ほかの方の記事を参考にソリューションアーキテクトの本を読みました。
　模擬試験で問われた内容がこの本に載っており、
　ソリューションアーキテクトの分野にも目を通しておいたほうが最低限読むことで
　クラウドプラクティショナーに必要な知識を学習できると感じました。

　また、AWSのホワイトペーパーも読みました。
　AWSについてのホワイトペーパーは試験のシラバスに近いので
　一通り見て内容を理解できていないと合格は難しいんじゃないかなぁと思います。
　
　なんとかクラウドプラクティショナーの範囲を網羅したと思った段階で試験に臨みました。

#3 本番試験
　(私の場合)会場に入って受付をしたらロッカーに荷物を預けて免許証とクレジットカードを持って試験を受けました。
　時間は90分でしたが、たくさん時間が余ったので3回見直しをしてから試験を終了しました。
　
　
#4.感想・結果
　1.結果
 　　815点で合格でした。2週間足らずの勉強で合格できたのはよかったです。
　2.感想
　　基本的にシステムインフラを構築できる人間であれば、難しくない内容でした。
　　しかしAWS特有のサービス名や、サービスの役割を0から覚えるのは、それなりに大変だと思います。
　　
　　(インフラSE向け)
　　物理基盤の名称をAWS特有のサービス名に置き換えて考えるだけなので、
　　インフラの役割を特有のサービス名に当てはめていけば、問題そのものは簡単だと思います。
　　他の方の記事も参考に、参考書や模擬試験を受けて挑めば2週間もあれば合格できると思います。
　　ただし**慢心ダメゼッタイ**
　　模擬試験で問題の雰囲気とレベル感がわかるので、それを踏まえて勉強すれば大丈夫です。

　　(非エンジニア向け)
　　逆にシステムインフラを理解していなければ0ベースで勉強することになるので大変だと思います。
　　

　　広く浅く問われるので、クラウドインフラの基礎を抑えるにはとても良い試験です。
　　しっかりと参考書やホワイトペーパーを理解していれば合格できる内容なので頑張ってください。
　　
　　今回の勉強でソリューションアーキテクトの本も読んだので忘れないうちにソリューションアーキテクトも受講していこうと思います。
SwiftでQiitaのトレンドを取得して表示させる

## QiitaのAPIにはトレンドを取得するAPIが存在しない
現在、SwiftUIでQiitaの記事を参照することができるクライアントアプリを作成中です。
トレンドの記事をリスト化して表示できたらいいなと思っていたらまさかのAPI自体提供されていない...
他のQiitaの記事でも同じようなことを実現させようと新たにQiitaのトレンドAPIを非公式で公開してるエンジニアも...

今回iOSネイティブアプリを作成しているので、Swiftだけで解決できないか試してみました！

## SwiftSoup
- HTMLをパース(解析)してくれるライブラリ 
- https://github.com/scinfu/SwiftSoup
- Cocoapods、Carthage、Swift Package Manager対応

## Qiitaのトップページを解析する
```swift
import SwiftSoup
import Combine

// Qiitaのページ(1日)
let urlString = "https://qiita.com/"
// 週間: https://qiita.com/?scope=weekly
// 月間: https://qiita.com/?scope=monthly

// タスクの初期化
var task = : AnyCancellable?
// URLに変換
let url = URL(string: urlString)!

// HTMLを取得
task = URLSession.shared.dataTaskPublisher(for: url)
    .receive(on: DispatchQueue.main)
    .sink(receiveCompletion: { completion in
        switch completion {
        case .finished:
            print("成功")
        case let .failure(error):
            print(error)
        }
    }, receiveValue: { data, _ in
        do {
            let text = String(data: data, encoding: .utf8)!
            
            // ここからSwiftSoupでパース
            let doc: Document = try SwiftSoup.parse(text)
            let link: Element = try doc.select("div[data-hyperapp-app=Trend]").first()!
            let json: Data = try link.attr("data-hyperapp-props").data(using: .utf8)!
            
            // Codableでデコード
            let response = try JSONDecoder()
                .decode(TrendResponse.self,
                        from: json)

            /// edgesにトレンドの記事が格納される
            print(response.trend.edges)
        } catch {
            print("エラー")
        }
    })
```

### Codable
```swift
struct TrendResponse: Codable {

    let scope: String
    var trend: Trend

}

struct Trend: Codable {

    let edges: [Edges]

}

struct Edges: Codable {

    let followingLikers: [Author]
    let isLikedByViewer: Bool
    let isNewArrival: Bool
    let hasCodeBlock: Bool
    let node: Node

}

struct Node: Codable {

    let createdAt: String
    let likesCount: Int
    let title: String
    let uuid: String
    let author: Author

}

struct Author: Codable {

    let profileImageUrl: String
    let urlName: String

}

```

## 完成した画面
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470777/fd6ccff5-b165-9107-4d45-28328c2be18a.png" width="300">  <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470777/6612cd7b-e7e8-c180-12c2-f00e6302529d.png" width="300">

## まとめ
- SwiftでHTMLを取得しパースすることで実現することができた。
- 現在、SwiftUIでクライアントアプリを絶賛開発中です。
- TestFlightでテスト配信もしているので、ご興味がある方は、コメントまたは連絡ください！

## 参考記事
- [Netlify Functions を使って Qiita のトレンド API を非公式で作ってみた](https://qiita.com/7ma7X/items/803f9599cde72810f1a8)
CentOS 8.0 でパッケージがインストールできなくなったら

CentOS 8.0 で `rpm` パッケージをアップデートすると、OS バージョンを表す DNF 変数 `$releasever` が 8 から 8.0 に変わり、DNF リポジトリの URL にアクセスできなくなり、パッケージをインストールできなくなってしまうようです。

```shell-session
# dnf -y install httpd
Error: This command has to be run under the root user.
CentOS-8.0 - AppStream                           26  B/s |  38  B     00:01
CentOS-8.0 - Base                                22  B/s |  38  B     00:01
CentOS-8.0 - Extras                              14  B/s |  38  B     00:02
Failed to synchronize cache for repo 'AppStream', ignoring this repo.
Failed to synchronize cache for repo 'BaseOS', ignoring this repo.
Failed to synchronize cache for repo 'extras', ignoring this repo.
No match for argument: httpd
Error: Unable to find a match
```

この問題は `dnf` パッケージをアップデートすれば解消しますが、そのままではインストールと同じくアップデートもできないので、`--releasever` オプションで OS バージョンを指定する必要があります。

```shell-session
# dnf --releasever=8 -y update dnf
(省略)
Upgraded:
  dnf-4.2.7-7.el8_1.noarch
  dnf-data-4.2.7-7.el8_1.noarch
  dnf-plugins-core-4.0.8-3.el8.noarch
  libdnf-0.35.1-9.el8_1.x86_64
  librepo-1.10.3-3.el8.x86_64
  libsolv-0.7.4-3.el8.x86_64
  python3-dnf-4.2.7-7.el8_1.noarch
  python3-dnf-plugins-core-4.0.8-3.el8.noarch
  python3-hawkey-0.35.1-9.el8_1.x86_64
  python3-libdnf-0.35.1-9.el8_1.x86_64
  python3-librepo-1.10.3-3.el8.x86_64
  yum-4.2.7-7.el8_1.noarch

Installed:
  yum-utils-4.0.8-3.el8.noarch

Complete!
```

これでパッケージをインストールできるようになります。
Python3における、ファイルを開く関数(openとcodecs.openの違いと速度比較について)

## まず結論
処理速度はopen関数の方が早い。
用途の広さではdocecs.open関数。
ソースコードの読みやすさ・シンプルさはどっちもどっち。
要は使いどころ次第でした。

## きっかけ
python3の練習用に、皆様ご存知"言語処理100本ノック"をやっていると、
ファイルを開く関数が2種類あることに気付いた(openとcodecs.open)。
どちらもよく使われているっぽい。

## openとcodecs.openは何が違うの？
codecs.open関数は、Python2系でエンコードしたファイルを開ける。
うん、まぁ、便利かもなぁ。
使いどころの違いとしてはそんな感じだと理解しました（指摘あれば教えてください）。

ただ、ソースコードの書き方に若干の違いがあります。以下で見ていきましょう。

## ソースコードの比較
以下のようなhoge.txtを読み込むコードを作成してみます。
![hoge.txt](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180125/1761c77b-f64e-9470-132a-4ee81bb4b08d.png)

### openのソースコード
![open_code](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180125/336fd90a-c8e4-5062-6331-5f60c29eab6c.png)
実行結果↓
![open_result](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180125/73e3e07f-0125-7cfa-8958-755c4292c6fb.png)

open関数は、標準ライブラリに入っているため、特別importの必要はない。
そのぶん行数は短くなるが、引数名の指定が必須で野暮ったくも見える。

### codecs.openのソースコード
![codecs.open_code](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180125/cdd4d142-5efa-b83d-56b6-7211ecd96293.png)
実行結果↓
![codecs.open_result](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180125/73e3e07f-0125-7cfa-8958-755c4292c6fb.png)

codecsライブラリをimportする必要がある。
しかし引数名の指定がないぶん1行が短く、スマートに見える。

## 実行速度の比較
100万回の上書き処理をさせ、その速度を比較する。
なお、実行は5回づつ行った。

### 比較プログラムのソースコード


## 結果
![final_result](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180125/c3bf8853-dc1b-c296-ba94-9d867ab1edb1.png)


以上の計測結果が出た。
open関数の方が約3倍速かった。
まるで赤い彗星。

## 結論(冒頭の結論と同じこと書いてます)
処理速度はopen関数の方が早い。
用途の広さではdocecs.open関数。
ソースコードの読みやすさ・シンプルさはどっちもどっち。
要は使いどころ次第でした。
AWS 認定ソリューションアーキテクト – アソシエイト、合格手順

2020/01/13(月)
AWS 認定ソリューションアーキテクト – アソシエイト を取得しました。

過去には、
　Oracle Master Gold Oracle9i Database、
　Sun時代のJava Webコンポーネントデベロッパ
を取得しました。

そんな私が久々に資格試験に向けて勉強し、合格した手順をご紹介します。
また、過去の手順と比べて変更した部分、不要だったかな？と思った事も含めます。

ちなみに、結論から書きます。
結論に腹落ちするため、各手順は、Why（なぜ？）、How（どのように？）、What（なにを？） の3本柱でご説明します。

# 結論
Udemyの講義と問題集をやれば受かります。
参考書とかは不要でした。。

# 手順
## 1つ目
### Why
試験勉強というと、問題集！と思い、Udemyの過去問に着手しました。
● 過去問
AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集（5回分325問）

ただ、過去問の解説がさっぱり分かりませんでした。
なので、過去問の解説を理解できるようになる！
### How
Udemyの22時間のAWSの講義
● 講義
これだけでOK！ AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座（初心者向け22時間完全コース）
## What
講義を受ける！
## 余談
HowをUdemyの22時間のAWSの講義を受ける！ と書きましたが、Udemyの講義以外に無駄なことをしたので、ご紹介。
### 無駄なこと
+ 参考書を買って読む。→ Udemyの講義で十分です。文字より動画で見たほうが頭に入りやすかったです。
+ 参考書を更に買って読む → Udemyの講義で十分です。

## 2つ目
### Why
試験の問題形式に慣れる必要がある。
### How
問題集！
● 過去問
AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集（5回分325問）
### What
問題集をやる！
Word Pressテーマ：STORKを使用したWebサイトに発生したエラーを解決するために行った処理

＊プログラミング超初心者です。閲覧していただいた方にわかりやすい表現を意識していますが
　①分かりにくい点
　②間違っている点
ありましたら、ご指摘ください🙏

***それでは早速***
#STORKを使用したWebサイトに発生したエラーを解決する
##【症状】
###Webサイトの上部にエラーメッセージが表示される
メッセージ本文
　　　<strong>"Notice:Undefined variable:icon in /~ファイルパス省略~/wp-content/themes/jstork/library/shortcode.php on line 226"</strong>
##【状況】
・テーマをアップデートしたら発生した
・吹き出しを使用しているページに表示されるっぽい（←サイト運営者推察）

##【やったこと】
1. エラーメッセージを読んでみる
  （ファイルパス省略）/library/shortcode.php の226行目にある"$icon"ってなんですの？の意味

2. (ファイルパス省略）/library/shortcode.php 226行目を確認する
    - 方法1：サーバーからローカル環境に本番環境を構築して確認する
        - FTPソフトにて"jstork"をローカルのwordpress環境>wp-content>themeの中にダウンロード
        - > JSTORK > library > shortcode.php を選択し226行目の記述内容を確認する...①
    - 方法２：管理画面から確認してみる方法
        - WordPress管理画面 > 外観 > テーマエディターに進んで”stork(親テーマ本体)”を選択
      > ①を実行
    
3. 記述の内容を確認(以下コードのコピペ)

			// コンテンツボックス
		function contentboxFunc($atts , $content = null) { ...A
			if($atts && $content) {																		
				$class = (isset($atts['class'])) ? esc_attr($atts['class']) : null;						｜
				$title = (isset($atts['title'])) ? esc_attr($atts['title']) : null;						｜
				$type = (isset($atts['type'])) ? ' type_'.esc_attr($atts['type']) : ' type_normal';		｜....B

				if(!$title && $class) {																	｜....C
					return '<div class="c_box ' . $class . $type .'">' . $icon . do_shortcode($content) . '</div>';｜...D＊

				} elseif($title && $class) {
					return '<div class="c_box intitle ' . $class . $type .'"><div class="box_title"><span class="span__box_title">' . $icon . $title . '</span></div>'. do_shortcode($content) .'</div>';													｜...D＊
				}
			}
		}
		add_shortcode('box','contentboxFunc');

		↑この中でエラーが発生していた。

	-記述の内容の概要-
		A：ファンクションcontentboxFuncをこう定義しまっせー
		B:このファンクションで使う変数はこれらでっせー
		C:さあ実行しましょう！
		D＊：＄iconて何？！　<-ここがエラー

4.上記を受けてBのなかに$iconを定義する一文を追記しました（221行目）

	218行目	$class = (isset($atts['class'])) ? esc_attr($atts['class']) : null;	
	219      $title = (isset($atts['title'])) ? esc_attr($atts['title']) : null;	
	220      $type = (isset($atts['type'])) ? ' type_'.esc_attr($atts['type']) : ' type_normal';	
	221      $icon = (isset($atts['icon'])) ? esc_attr($atts['icon']) : null;*	
意味：もし、＄attsの中のiconが入力されていたらiconのURLを$iconに入れる、そうでなければ$iconにnullを入れる..(この解釈ちょっと怪しい。)
				　　 


###以上の処理でエラーは表示されなくなりました。

【やってみて思ったこと】
・管理画面からファイルを編集することもできるけど、本番環境での調整になるので
　ローカル環境にダウンロードして作業した方が、心理的にもエラーが発生するリスク回避の面でも
　メリットがある。
・予想していたショートコードに関するエラーではなかったので、実際に発生している事象は自分の目で
　確認する。

**忘備録と自分log**
Swiftの記号あれこれ

#背景
Swiftの公式ドキュメント、ヘルプガイド、ブログのコードサンプルなどによく出てくる実装のなかで、どんな意味があるのかすぐに判断できない記述がありました。
メソッドの引数が顔文字化していたり（例えば、`max(:_:_)`とか）、変数定義の型の最後にに`?`や`!`が付いていたりと、あれ？これはどういう意味だったかなというときに自分自身がすぐに思い出すとき用の記事があるといいなぁと思い記事にしました。

#対象とする読者
Swift初心者

#環境
私がこの記事を書いている際に利用しているのは次の環境です。
Xcode 11.3.1
Swift 5.0

#Swiftの記号あれこれ

###関数の引数に出現する_ (アンダースコア)

Swiftでは関数の引数にラベルをあらかじめ付けておき、利用者にそれを明確に指定させることができるが、名前をわざわざ指定しなくても明らかにわかる場合は、その仕組みだとコードが読みにくくなってしまいます。
なので、関数呼び出しするときの引数が、名前なしで渡せますよということを明示するもの。

```swift
// 引数に名前付きで呼び出してもらう関数の書き方
func add(x: Int, y: Int) -> Int {
    return x + y
}
var r1 = add(x: 3, y: 2)  // 5: OK
var r2 = add(3, 2)        // NG(引数に名前がないのでコンパイルエラー)


// 引数に名前なしで呼び出してもらう関数の書き方
func addByNoLabel(_ x: Int, _ y: Int) -> Int { 
    return x + y
}
var r3 = add(4, 7)        // 11: 引数に名前なしでOK
```

関数のシグネチャーで、
`func(_:)`とか`func(_:_:)`とかの表現を見かけたときは、`_:`のところに、名前なしで引数を入れれば利用できるんだな、ぐらいで見ておけばよいです。

###型のうしろに?（はてな）
`?`
通称：はてなマーク
正式名：クエスチョンマーク

値がオプショナル型であることを示す場合に利用します。オプショナル型は、指定した型の値もしくは値そのものがない`nil`のいずれかを表す型です。
`Optional<Wrapped>`  (WrappedにはInt,Stringなど実際の型が入る)が入りますが、コードが冗長となるのを避けるためのシュガーシンタックスとして用意されています。

```swift
// 正式な構文だと
var age: Optional<Int>

// 簡潔に書くと
var age: Int? = 21

// 利用時には、アンラップが必要（強制アンラップした場合）
var nextAge :Int = age! + 1   // 22: オプショナルの値に!を付けて強制アンラップ
```


変数等の後ろに`?`が出現した場合は、この変数は空っぽの状態(nil)もあり得るということと、Optionalを解除(Wrap包み紙から出してあげるイメージ)しないと、元の型としては利用できないという認識を持っておけばよいです。


###型のうしろに!（びっくり）

`!`
通称：びっくりマーク
正式名：エクスクラメーションマーク

こちらもオプショナル型ですが、`?`とは異なり`!`で定義した値にアクセスする際には自動的に強制アンラップして元の型にしてくれます。なので「暗黙的にアンラップされた`Optional<Wrapped>`型」と呼ばれています。
型としては、`Optional<Wrapped>`型だけど、利用するときには通常の`Wrapped`型として利用可能。
注意点としては、値にアクセスしたときに`nil`だった場合は、実行時エラーとなってしまいます。

```swift
var age: Int! = 21

//アクセス時に自動的に強制アンラップしてくれる
var nextAge: Int = age + 1   // 22
```


###範囲演算子（終了を含まない）

`a..<b`
aから始まり、終了bを含まない範囲。

```swift
var range 1..<4   // CountableRange(1..<4) 

for value in range {
    print(value)
}

実行結果
1
2
3
```


###範囲演算子（終了を含む）

`a...b`
aから始まり、終了bを含む範囲。

```swift
var range 1...4   // CountableClosedRange(1...4) 

for value in range {
    print(value)
}

実行結果
1
2
3
4
```

#さいごに

慣れない言語でのコーディングは不安です。
でも、知ってしまえば、慣れてしまえばそれほど難しくないことは多々あります。
私も今回のこの記事を自分で整理してアウトプットすることで、頭の中を整理できました。
私のようなSwift初心者の方に、この記事が少しでも役立てば幸いです。
Mac　ゴミ箱に入れたディレクトリが削除できない..


# 問題：ダウンロードしたファイルの入ったディレクトリを削除できない
→「項目〇〇は使用中のため削除できない」とのメッセージが出る

# 結果：ファイルに権限を与えたら削除できました

（参考）
http://yagays.github.io/blog/2013/07/13/directory-permission/
https://support.apple.com/ja-jp/guide/mac-help/mchlp1203/mac



なんやかんや時間がかかってしまったので、その過程を備忘録として書きます。

## 1.削除したいディレクトリの構成

```
- maindir
    + dir1
        - file1
    + dir2
        - file2
```

## 2.試したこと（いずれも失敗）
・__関係ありそうなアプリを停止してからの削除__
　→　アクティビティモニタで該当アプリを選択し終了させた
（参考）https://support.apple.com/ja-jp/HT201464
・__セーフモード起動からのゴミ箱を空にする__
（参考）https://support.apple.com/ja-jp/HT201583

## 3.ターミナルから直接コマンドを入力し、削除する方法を試みた

```
＃ファイル削除の入力コマンド　（警告なし。ディレクトリとその中身を問答無用で削除する。実行前要確認）
rm -rf ディレクトリ名  
```
（参考）ターミナルコマンドまとめ
https://qiita.com/ryouzi/items/f9dee1540a04a0bfb9a3

実行結果は、Permission deniedされた。

```
#実行結果
$ rm -rf /maindir [削除したいディレクトリパス]
rm:/maindir/dir1/file1: Permission denied
rm:/maindir/dir2/file2: Permission denied

```
なぜか拒否された、、一度ディレクトリの権限について調べてみた。

```
:file1$ ls -l 
total 0
srwx------  1 daemon  daemon  0  2  4 08:36 file1

#その他ユーザーの権限がない模様

```
（参考）chmodコマンド
https://do-zan.com/mac-terminal-chmod/

ターミナルからchmodコマンドで権限付与を試みたがうまくいかず。

## 4.Finderからファイルに権限を付与をしてみた

１）ゴミ箱にある削除したいデータを右クリックし情報をみる

<img width="277" alt="スクリーンショット 2020-02-11 16.38.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492712/1356973b-7e61-e45c-0417-54ae408756bc.png">

２）アクセス権を確認。今回の場合読み出しのみとなっていたので、ロックを解除し「読み書き」を選択する
<img width="267" alt="スクリーンショット 2020-02-11 16.39.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492712/ce12f309-185b-a422-1674-20ffb032d5f5.png">

そのあとターミナルで該当ディレクトリまでcdし、rm -rfコマンドを入力して削除できました。
【Mac】PC起動時にRTSP対応のカメラ映像を自動再生

# 概要
Macを起動した際に自動でストリーミング配信映像を再生する方法について書きたいと思います。
展示会や説明会などでPCを起動したら自動でストリーミング配信映像を流したい時に活用

- 手順
    - ffplayでストリーミング映像を表示出来るか確認
    - ffplayを実行するスクリプトを書く
    - Macで上記スクリプトを起動時に実行するように設定
    - 確認方法

# 実施手順
*<font color="Red">①　ffplayでストリーミング映像を表示出来るか確認</font>*
まずffplayを実行するためにbrewでダウンロード。ffmpegをDLすると一緒にffplayが入ります。

```
$ brew install ffmpeg
```
次にffplayでRTSPプロトコルの映像を再生

```
$ ffplay rtsp://ユーザ名:パスワード@IPアドレス:ポート番号/動画再生URL
例）$ ffplay rtsp://admin:hogehoge@192.168.1.100:554/axis-media/media.amp
```

*<font color="Red">②　ffplayを実行するスクリプトを書く</font>*
シェルスクリプトを書く

```
$ cat rtsp.sh
#!/bin/bash

# 下記rtspは適宜置き換える
/usr/local/bin/ffplay rtsp://admin:hogehoge@192.168.1.100:554/axis-media/media.amp
```
実行権限を付ける

```
$ chmod +x rtsp.sh
```

*<font color="Red">③　Macで上記スクリプトを起動時に実行するように設定</font>*
~/Library/LaunchAgents配下にplistを作成。今回はrtsp.plistという名前で作成
※　<string>/Users/ユーザ名/rtsp.sh</string>の部分は②で作成したシェルスクリプトを指定

```
$ cat rtsp.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>test</string>
    <key>Program</key>
    <string>/Users/ユーザ名/rtsp.sh</string>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>
```

plistの設定を反映させる

```
$ launchctl load ~/Library/LaunchAgents/rtsp.plist
```

*<font color="Red">④　確認方法</font>*

Macを再起動してストリーミングが自動で再生出来たらOK。
再起動に時間がかかる場合は以下のコマンドを実行することで確認が出来ます。

```
$ launchctl unload ~/Library/LaunchAgents/rtsp.plist
$ launchctl load ~/Library/LaunchAgents/rtsp.plist
```
[AWS]DBレイヤを冗長化する方法

**2020年2月11日現在の内容です。**

構成イメージ
<img width="1192" alt="スクリーンショット 2020-02-11 16.26.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397642/c6ce4ebd-4436-f05d-456c-d0d24c6afc03.png">

## マスタースレーブ構成の作成
**RDSではマルチAZ機能でマスタースレーブ構成を構築できる**

AWSコンソールからRDSを検索し、クリック
<img width="1680" alt="スクリーンショット 2020-02-11 16.32.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397642/dc932f90-8fba-0d3d-ce0e-4e08c0d2f01a.png">

サイドバーから「データベース」をクリック
<img width="1680" alt="スクリーンショット 2020-02-11 16.34.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397642/ef7e2c84-a22d-f6ff-45fb-c9477b92752b.png">

対象のデータベースをクリック
<img width="1680" alt="スクリーンショット 2020-02-11 16.35.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397642/50154dfb-6611-718d-a57e-48ee6868c07f.png">

「変更」をクリック
<img width="1680" alt="スクリーンショット 2020-02-11 16.37.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397642/f6d2202b-6cae-a1ae-d38d-ab9cf69ad904.png">

マルチAZ配置を「はい」に変更し、「次へ」をクリック
<img width="1680" alt="スクリーンショット 2020-02-11 16.39.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397642/1e86c293-46ab-ff09-cfec-54e3fa12e59c.png">
<img width="1680" alt="スクリーンショット 2020-02-11 16.41.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397642/f59fddac-6848-5b60-3697-a4238a24c7ab.png">

すぐに適用にチェックし、「DBインスタンスの変更」をクリック
<img width="1680" alt="スクリーンショット 2020-02-11 16.43.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397642/44a0c94f-0294-555f-802b-07df1506a83d.png">

マルチAZが「あり」になっていることを確認
<img width="1680" alt="スクリーンショット 2020-02-11 16.54.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397642/f213109c-64eb-900a-b630-fb63265ba553.png">

**注：マルチAZ配置にするとRDSが複数起動している状態となるので、料金が高額になる可能性がある**

## 参考
[AWS：ゼロから実践するAmazon Web Services。手を動かしながらインフラの基礎を習得](https://www.udemy.com/course/aws-and-infra/)
angularをFirebaseでデプロイ

# 趣旨
angularとdjangoで作ったブログアプリのangularの方をFirebaseでデプロイします。
メモ程度にまとめるつもりです。

# アカウントとプロジェクトの作成
Firebase公式サイトで行います。
アカウントは、なぜか作ってありました。まず『プロジェクトの追加』を押して、プロジェクトを作成します。なんとかに同意みたいなことがいっぱい出てきますが、かたっぱしから同意します。

# Hosting
今回は『Hosting』という機能を使うので、『開発』→『Hosting』を選択します。
始めたいので、『始める』を選択します。

# Firebase CLI
『Firebase CLI』を使うので、指示に従ってターミナルに移動してインストールします。


```terminal:ターミナル
$ cd アプリのディレクトリ
$ npm install -g firebase-tools
```

 # ターミナルでログイン
以下のコマンドを打って、FirebaseCLIにログインします。

```terminal:ターミナル
$ firebase login
```
そしたらいろいろ出てきて指示に従ってぽちぽちしていけばいつの間にかターミナルでログインできています。

# プロジェクトをビルドする

```terminal:ターミナル
$ ng build --prod
```
このコマンドを打って、ファイルの中にエラーが残っていた場合はエラーを吐かれます。

※次のプロジェクトの初期化の前にビルドをして`dist`ディレクトリを作成する必要があります。

# プロジェクトの初期化

```terminal:ターミナル
$ firebase init
```
そしたらめっちゃ質問されるので、全部英語を読んで頑張って答えます。

『What do you want to use as your public directory?』
と聞かれたら、
『dist/アプリのディレクトリ名』と答えます。

# テスト
デプロイする前にローカルサーバーで動作を確認します。

```terminal:ターミナル
$ firebase serve
```
想定通りにアプリが動いたらいよいよデプロイです。

# デプロイ

```terminal:ターミナル
$ firebase deploy
```

完了したらURLが出てきます。そのURLに飛んだら自分の作成したアプリが表示されます。
表示されずに『Welcomeなんとか』って表示される場合は、『⌘+シフトキー+R』でキャッシュを消してみると現れると思います。
ESP32 - MicroPythonにて、IFTTT-Webhooksにトリガーを投げる

# はじめに

ESP32 - MicroPythonを使い、IFTTT-Webhooksへのリクエスト方法について記載します。<br>
※IFTTTの紹介や設定手順は割愛します。


# 開発環境

以下が確認した環境となります。

- ホストPC
  - windows10 64bit Home
  - VSCode - 1.41.1
     - Pymakr 1.1.5
  - NodeJS - 12.14.1 LTS
- ターゲット
    - MicroPython v1.12 on 2019-12-20; ESP32 module with ESP32

# 機材

|項目  |型名|備考  |
|---|---|---|
| ESP32-WROOM-32 開発ボード  |[NodeMCU-32S ESP32-WROOM-32]

# コード

動作確認したコードは以下となります。


ファイル名：sample_ifttt.py

```
import urequests as requests
import time

SSID = "xxxxxxxxx"  # アクセスポイントのSSID
PASSWORD = "xxxxxxxxx" # アクセスポイントのパスワード
MY_KEY = "xxxxxxxxx" #IFTTT - webhooks - tokenを指定
EVENT_ID = "xxxxxxxxx" # 登録したwebhooksのイベント名を指定

def do_connect():

    import network
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    if not wlan.isconnected():
        print('connecting to network...')
        wlan.connect(SSID, PASSWORD)
        while not wlan.isconnected():
            pass
            time.sleep(1)
    print('network config:', wlan.ifconfig())



# IFTTT_Webhook
def ifttt_webhook(eventid):

    # valueに載せる情報
    payload = "value1="
    payload += "dummy1"
    payload += "&value2="
    payload += "dummy2"
    payload += "&value3="
    payload += "dummy3"

    url = "http://maker.ifttt.com/trigger/" + eventid + "/with/key/" + MY_KEY

    response = requests.post(url, headers={"Content-Type": "application/x-www-form-urlencoded"}, data=payload)
    # value指定が不要な場合は↓でok
    # response = requests.post(url)

    response.close()

# wifiへの接続
do_connect()

# ifttt-webhooksへのトリガー
ifttt_webhook(EVENT_ID)

```

# 実行方法

```
>>> import sample_ifttt
```

→コードで指定したイベントがよばれること確認



# メモ


## valueの指定について

ここが一番はまりました。


以前、Python3.7でIFTTTへのリクエストを行うコードを以下のように書きました。。

```
import requests

def ifttt_webhook(eventid, values):
    payload = {"value1": "",
                "value2": "",
                "value3": "" }
    payload["value1"] = values[0]
    payload["value2"] = values[1]
    payload["value3"] = values[2]

    url = "https://maker.ifttt.com/trigger/" + eventid + "/with/key/" + my_key
    print(url)
    response = requests.post(url, data=payload)
```

これをMicroPythonでそのまま記載すると、エラーにはなりませんが、valueが適用されません。

[urequests](https://github.com/micropython/micropython-lib/tree/master/urequests)のコードを確認したところ、jsonで指定しないとダメなのかなという感じでした。

そこで、json指定したのですが、urequestsの中で、ヘッダが固定文字で渡されており、
"Content-Type: application/x-www-form-urlencoded"
がのらないことが分かりました。

というわけで、headersとdataをそれぞれ指定して、
valueに適用させしました。


# 参考にさせていただいたサイト

* [github - urequests](https://github.com/micropython/micropython-lib/tree/master/urequests)
開発する上でエンジニアに気付いてほしいこと

# エンジニアの人にお願いしたいこと

自分は発注側の立場にいることもあり、ユーザに近い立場でサービスを見守っています。
今回は日々業務をしていて感じたことをまとめてみます。
とは言いつつ、感想は1点だけなので10分もあれば読み終わります。

## どうか、システムは速度を大切にしてください。

時は金なりです。
エンジニアが一生懸命作ったシステムでも、速度が遅ければたちまちそのシステムはゴミと化します。[^1]
理由は"Time is Money"です。
以前と比較して業務効率を下げる様なシステムはコストが掛かります。
大抵は一人が使うシステムではなく全社的なシステムになると思いますので、
システムが全社的に実損を与えていることになります。
コストがより掛かるということは、その分だけシステムの利用に時間(お金)を使っているので
開発側はその自覚を持って製作に臨んで頂ければと思います。[^2]

## とはいえ、開発って難しいなと思います。

中々、開発側は作ることに集中してユーザーにまで意識は出来ない仕事かと思います。
しかも、色々な部署のことを考えたシステムを作らないといけないと考えたときに、リスキーな仕事だなと思います。
心中はお察ししますが、ビジネスの観点では利用者目線でよろしくお願いいたします。

おわり。

[^1]: もちろん機能を満たすことは大事な要件ではありますが、軽度の不備などがあり仮に完璧ではないにしても、同時に速度は考えていかないと利用する側にとってリスクのある話題になるかと思います。

[^2]: 何事にもコストは使いますが比較をしたときに、以前より時間を掛ける必要性が増えたのであれば、本来は掛けなくてよいコストが増加したと考えられるため、無駄（非効率）なお金が増えたと考えられるかと思います。
RaspiにUbuntu入れてその上にDocker入れてコンテナからpythonでGPIO制御

#はじめに
めちゃくちゃややこしいタイトルになってしまいましたがこんなイメージです
<img width="503" alt="スクリーンショット 2020-02-11 14.56.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243994/4fc4b46f-5b72-5a40-ab6d-a3f6a3e38584.png">

#環境
開発PC：Mac Mojave
RaspBerry Pi4 メモリ4GB
SDカード16GB

#Ubuntu19.10をSDに書き込む
https://ubuntu.com/download/raspberry-pi
から64bit版をダウンロードして[balenaEtchar](https://www.balena.io/etcher/)を使って書き込みました。

#dockerをUbuntuにインストール
Ubuntuにsshかなんかで入って

```
sudo apt-get install docker-ce
```

でインストールできます。

```
sudo usermod -aG docker ubuntu
```

でsudo使わなくてもdockerできます。

#ベースイメージを作る
開発PCでpython scriptを書いてからDockerfileでdockerImageにコピーしてもよいのですが、わかりづらかったので一度Dockerfileでベースを作ってから、コンテナに入りそのコンテナからイメージを作ります。

Dockerfileです

[Raspberry Pi で TensorFlow する Docker 環境構築](https://qiita.com/kohbis/items/53c27ce6c62a7039aaa2#raspberrypi-%E3%81%AB-docker-%E3%82%92%E3%81%88%E3%81%84%E3%82%84)
を参考にさせていただきました、この記事ほぼほぼ上を参考にしました。
rpi.gpioを入れたかったのですが入れ方よくわかんなかったのでそのまま記述してます

```DockerFile
FROM resin/rpi-raspbian:stretch

RUN echo "deb http://mirrordirector.raspbian.org/raspbian/ stretch main contrib non-free rpi firmware" > /etc/apt/sources.list

RUN apt-get update -y
RUN apt-get install -y --no-install-recommends \
        vim git less wget \
        build-essential \
        libatlas-base-dev \
        python3-pip python3-dev python3-setuptools\
        python3-scipy python3-h5py \
        libraspberrypi-bin \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

RUN pip3 install --upgrade pip setuptools
RUN pip3 install rpi.gpio
```

あとはbuildします

```bash
docker build -t rpi/rpi:0.1 .
```
docker imagesでできてることを確認しましょう！できてるはずです。

#コンテナを起動してpythonスクリプトを書く
先ほど作ったイメージからコンテナを起動します。
```bash
docker run --name rpi_test -ti --privileged rpi/rpi:0.1 /bin/bash
```
で、コンテナの中に入るので、欲しいものをインストールします。nano派なので

```bash
sudo apt-get update
sudo apt-get install nano
```
homeに移動してscriptを作ります。
この辺ほんとは作業ディレクトリとか設定するのがよいのだろうな・・・

```bash
cd home
nano test.py
```

GPIO17にLEDをさして適当にLチカするプログラムです。

```python

import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD)
GPIO.setup(11, GPIO.OUT)
while True:
    GPIO.output(11, True)
    time.sleep(2)
    GPIO.output(11, False)
    time.sleep(2)
```
スクリプトを保存したら

```
exit
```
でログアウトしてください



```bash
docker ps -a
CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS                     PORTS               NAMES
e700d8490be8        rpi/rpi:0.1           "/usr/bin/entry.sh /…"   11 minutes ago      Exited (0) 6 seconds ago                       rpi_test
```

コンテナが止まっています。このコンテナからイメージを作るには

```bash
docker commit rpi_test rpi/rpi:0.2
docker images
REPOSITORY           TAG                 IMAGE ID            CREATED             SIZE
rpi/rpi              0.2                 50f7f2a406e7        2 minutes ago       622MB
```
scriptが保存してあるイメージができました。

#起動

```bash
sudo docker run --privileged -it -d --name rpi -w /home rpi/rpi:0.2 python3 test.py
```

バックグラウンドでコンテナが動いてLちかし続けます！
止めたい時は docker stop rpiでとまります

#まとめ
センサーデータとかもそのうちとりたい