Python3でpyserialを使う

# はじめに

何年か前はWindows7 64ビットで，Python3だとpyserialが使えなかったような気がしたが，どうも最近になって使えるんじゃないかという雰囲気を感じ取った．なので，インストールするとこからやってみた．

最後のまとめに要点を書いたので，時間が無い人はそちらへ．

# インストール作業

さっそくインストール作業に取りかかる．分からないことは大体，検索すれば誰かがやってる．

## インストールコマンド

Anacondaディストリビューションにインストールしたい．検索したらAnacondaのサイトにインストールコマンドが出てきたので，これで間違いなかろう．
[anaconda / packages / pyserial 2.7](https://anaconda.org/anaconda/pyserial "anaconda.org")

```
> conda install -c anaconda pyserial=2.7
```

予想はしていたが，やはりインストールできない．

## またプロキシか

エラーを見る限り，サーバにアクセスできていない．またプロキシ[^1]か．何らかの手段でプロキシ設定をすれば解決できる．Qiita検索で見つけた[mishan88氏](http://qiita.com/mishan88/items/2f9e1c5e9e2572ba8a36 "Qiita")によると，Anacondaのルートフォルダに`.condarc`ファイルを作って，そこにプロキシ設定を書けば良いらしい．Windowsでは'.'で始まるファイルは直接作れないから，後でrenするみたいな手法が書いてあったが，もしかして，Anacondaのルートフォルダでコピーコマンド使えば，適当な名前のファイルを作る作業を無くして1手稼げるんじゃないかな？

```
> copy con .condarc
^Z
        0 個のファイルをコピーしました。
```

あ・・・これダメだわ．多分，フォルダのアクセス権限が制限されてる．普通にエクスプローラでフォルダを開いて右クリックしても，新規作成でテキストファイルさえ作れない．権限変更すればいいだけだけど，それをやると負けた気がする．

リンクにあったcondaのマニュアルを見てみる．
[conda Configuration](https://conda.io/docs/config.html "conda.io")

なんか，コンフィグデータを追加すると，`.condarc`ファイルを勝手に作ってくれるらしいので，例示をそのまま実行してみる．

```
> conda config --add channels r
```

"C:\Users\\[User Name]\"に`.condarc`ファイルができた！やったぜ．俺は勝ったんだ！

メモ帳で開いて，さっき追加した`channels`は削除して，`proxy_servers`を書いて保存．

```
proxy_servers:
    http: http://[server address]:8080
    https: https://[server address]:8080
```

`conda config --show`で設定したプロキシがちゃんと表示されることを確認．

```
> conda config --show
...(省略)...
proxy_servers:
  https: https://[server address]:8080
  http: http://[server address]:8080
...(省略)...
```

よしよし．

## インストール

これでやっとインストールできる！えい！

```
> conda install -c anaconda pyserial=2.7
```

・・・・・・
・・・

できなかった．結局，Anacondaフォルダのアクセス権限が無いせいで，インストールができないのだ．

## インストール再び

"C:\Program Files\Anaconda3"フォルダの権限をフルアクセスに変更する．べ，別に負けてないもん！こんぴゅーた？とかいう奴が融通利かないのが悪いんだもん！！

```
> conda install -c anaconda pyserial=2.7
Fetching package metadata ...........
Solving package specifications: ..........

Package plan for installation in environment C:\Program Files\Anaconda3:

The following packages will be downloaded:

    package                    |            build
    ---------------------------|-----------------
    conda-env-2.6.0            |                0          498 B  anaconda
    pyserial-2.7               |           py35_0          45 KB  anaconda
    requests-2.12.4            |           py35_0         791 KB  anaconda
    pyopenssl-16.2.0           |           py35_0          70 KB  anaconda
    conda-4.3.11               |           py35_0         539 KB  anaconda
    ------------------------------------------------------------
                                           Total:         1.4 MB

The following NEW packages will be INSTALLED:

    conda-env: 2.6.0-0       anaconda
    pyserial:  2.7-py35_0    anaconda

The following packages will be UPDATED:

    conda:     4.2.9-py35_0           --> 4.3.11-py35_0 anaconda
    pyopenssl: 16.0.0-py35_0          --> 16.2.0-py35_0 anaconda
    requests:  2.11.1-py35_0          --> 2.12.4-py35_0 anaconda

Proceed ([y]/n)? y

Fetching packages ...
conda-env-2.6. 100% |###############################| Time: 0:00:00  12.15 kB
pyserial-2.7-p 100% |###############################| Time: 0:00:00  62.00 kB
...(以下略)...
```

よし！インストールできたぜ！

# 動作

さっそく動かしてみる．

## とりあえずインラインで

よその人がやってるようなことを，そのままやってみる．

```py3
>>> import serial
>>> ser = serial.Serial("COM1", 9600)
>>> print(ser.name)
COM1
```

よしよし，ちゃんと動いてるぞ．いよいよシリアルに書くぞ！

```py3
>>> ser.write("hello")
```

実行！

```py3tb
Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    ser.write("hello")
  File "C:\Program Files\Anaconda3\lib\site-packages\serial\serialwin32.py", line 283, in write
    data = to_bytes(data)
  File "C:\Program Files\Anaconda3\lib\site-packages\serial\serialutil.py", line 76, in to_bytes
    b.append(item)  # this one handles int and str for our emulation and ints for Python 3.x
TypeError: an integer is required
```

あれ？？？

## 動かない原因と対策

write関数がうまくいってない．検索したら見つけた．
[Python Serial write function not working](http://stackoverflow.com/questions/22835551/python-serial-write-function-not-working "Stack Overflow")
さすが，Stack Overflow．大抵のことはここで見つかる．

write関数の引数の型がダメっぽい．python2ではこれで大丈夫だったようだが，python3では明示的にbyte列にしないとダメらしく，文字列のままでは使えないようだ．変換は簡単で，文字列の手前に'b'を追加するだけで大丈夫のようだ．

```py3
>>> ser.write(b"hello")
5
```

よし，エラー無し！

・・・・・・
・・・

エラーが出ないけど，これ，動いてるのかな？
シリアルケーブルつないでないんだよなぁ・・・．

先のStack Overflowの記事によると，次のようにも書ける．

```py3
>>> data = "hello"
>>> ser.write(bytes(data, 'UTF-8'))
```

## 通信終わり

もちろん最後はクローズ．

```py3
>>> ser.close()
```

特筆すべきこと無し．

# まとめ

Python3でpyserialを動かすのは何とかなったっぽい．受信処理は全然試してないし，「っぽい」ってことで．

シリアルケーブルも無いのに関数だけ動かしてもしょうがない・・・・・・．
いや，今はまだつなぐべきときじゃないってだけで，そのうちつなぐんだからねっ！

## condaにプロキシ設定する

プロキシを使う場合は，`.condarc`ファイルにプロキシ設定を記述する．このファイルは次のコマンドを実行すると勝手に作ってくれる．

```
> conda config --add channels r
```

"C:\Users\\[User Name]\"に`.condarc`ファイルができる．これをメモ帳で開いて`proxy_servers`を書いて保存．

```
proxy_servers:
    http: http://[server address]:8080
    https: https://[server address]:8080
```

ファイル内に書かれている`channels`は不要なので削除してOK．

## インストールする

インストールコマンドはこれ．

```
> conda install -c anaconda pyserial=2.7
```

プロキシを使っている場合は，先のプロキシの設定をする．インストールできない場合は，"C:\Program Files\Anaconda3"のアクセス権限を確認，書き込み可能なように変更する．

## pyserialを使うときの注意

基本的にはPython2と同じようだが，Python3では文字列を明示的にbyte列に変換しなければならない．これは文字列の直前に"b"を追記するだけでOK．

```py3
ser.write(b"hello")
```

次のように書くこともできる．

```py3
>>> data = "hello"
>>> ser.write(bytes(data, 'UTF-8'))
```

---
[^1]: そう，またなのだ．[python3 urllibプロキシ設定](http://qiita.com/gazami/items/4b42371ed831c159fb04 "Qiita")