zshを使う

ずーーっとbashだったけれど、別に信仰があるわけじゃないので、いいかげんzsh使ってみる

参考リンクだけまとめる(自分が書かなくても他の人がいっぱい書いているからこれでいいや)

zshを使ってみる - Qiita

.zshrcの設定例(設定内容の説明コメント付き) - Qiita

最強のシェル zsh - Qiita

トラブル

zshにしたらpyenvが使えなくなった

zshにしたらpyenvが使えなくなった

djangoでも以下のようなエラーが出て焦る

[~/git/django-tutorial/tutorial/mysite] $python manage.py runserver                                                              (git)-[master]
  File "manage.py", line 14
    ) from exc
         ^
SyntaxError: invalid syntax
[~/git/django-tutorial/tutorial/mysite] $

~/.bashrcの中身を~/.zshrcにコピーするのを忘れていた

[~/git] $which pyenv                                                                                                             (git)-[master]
pyenv not found
[~/git] $sudo find / -name pyenv                                                                                                 (git)-[master]
[sudo] password for ludwig125:
/home/ludwig125/.pyenv/libexec/pyenv
/home/ludwig125/.pyenv/bin/pyenv
[~/git] $                                                                                                                        (git)-[master]
[~/git] $                                                                                                                        (git)-[master]
[~/git] $                                                                                                                        (git)-[master]
[~/git] $                                                                                                                        (git)-[master]
[~/git] $                                                                                                                        (git)-[master]
[~/git] $                                                                                                                        (git)-[master]
[~/git] $export PYENV_ROOT="$HOME/.pyenv"                                                                                        (git)-[master]
[~/git] $export PATH="$PYENV_ROOT/bin:$PATH"                                                                                     (git)-[master]
[~/git] $eval "$(pyenv init -)"                                                                                                  (git)-[master]
[~/git] $pyenv                                                                                                                   (git)-[master]
pyenv 1.1.5-8-g7b9d1a4
Usage: pyenv <command> [<args>]

Some useful pyenv commands are:
   commands    List all available pyenv commands
   local       Set or show the local application-specific Python version
   global      Set or show the global Python version
   shell       Set or show the shell-specific Python version
   install     Install a Python version using python-build
   uninstall   Uninstall a specific Python version
   rehash      Rehash pyenv shims (run this after installing executables)
   version     Show the current Python version and its origin
   versions    List all Python versions available to pyenv
   which       Display the full path to an executable
   whence      List all Python versions that contain the given executable

See `pyenv help <command>' for information on a specific command.
For full documentation, see: https://github.com/pyenv/pyenv#readme
[~/git] $which pyenv                                                                                                             (git)-[master]
pyenv () {
        local command
        command="$1" 
        if [ "$#" -gt 0 ]
        then
                shift
        fi
        case "$command" in
                (rehash|shell) eval "$(pyenv "sh-$command" "$@")" ;;
                (*) command pyenv "$command" "$@" ;;
        esac
}
[~/git] $ 

ということでこれを~/.zshrcにコピーする

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"  

pythonのpandasを使う

参考

Pandas でデータフレームを作ってみよう – Python でデータサイエンス

[Python] pandasの使い方まとめ - Qiita

Pandas の DataFrame の基本的な使い方 - akiyoko blog

10分でPandasを学ぶ - Qiita

Python Pandasでのデータ操作の初歩まとめ − 前半:データ作成&操作編 - Qiita

インストール

$ pip install pandas

csvファイルを出力

[~/git/work/src/python/memo/pandas] $ cat padas-test.py 
import pandas as pd

df = pd.DataFrame([
         ['a', 'b', 'c'],
         ['d', 'e', 'f']
     ])

df.to_csv("./output.csv")
[~/git/work/src/python/memo/pandas] $ python3 padas-test.py 
[~/git/work/src/python/memo/pandas] $ cat ./output.csv 
,0,1,2
0,a,b,c
1,d,e,f
[~/git/work/src/python/memo/pandas] $ 

Ubuntu14.0.4でホスト名とユーザ名を変更する

概要

VMのUbuntu14.0.4でホスト名とユーザ名を変更したのが意外と大変だったのでメモ

以下では、ホスト名も、ユーザ名も、gitアカウントと同じ「ludwig125」にすることを目指した

参考

Ubuntu14.04でホスト名を変更する - Qiita

ホスト名

ホスト名:hostnameコマンドの結果出力するUbuntuのホスト名を指す

ホスト名の変更は簡単だった

  • 以下のホスト名を変更するだけ
 sudo vim /etc/hostname
 sudo vim /etc/hosts

反映させるにはUbuntuの再起動が必要

確認

$ hostname
ludwig125-virtual-machine

※「-virtual-machine」の部分をつけたほうがホスト名として分かり易いのでつけた

ユーザ名の変更

ユーザ名:whoコマンドで出力されるユーザの名前

ユーザ名の変更はusermodで行う

Man page of USERMOD

usermodをする上での問題

しかし、自分のユーザ名を変更しようとしても、自分自身のプロセスがあるので変えられないという問題がある

$ sudo usermod -l ludwig125 <今のユーザ名>
usermod: user <今のユーザ名> is currently used by process 1495
$ 

別のユーザを作る

自分自身のプロセスが動いている状態で自分のユーザ名を変えられないので、別にユーザを作った (もっといい方法があるかもしれない・・・)

  • adduserで「temp_user」ユーザを追加
$ sudo adduser temp_user
ユーザー `temp_user' を追加しています...
新しいグループ `temp_user' (1001) を追加しています...
新しいユーザー `temp_user' (1001) をグループ `temp_user' に追加しています...
ホームディレクトリ `/home/temp_user' を作成しています...
`/etc/skel' からファイルをコピーしています...
新しい UNIX パスワードを入力してください: 
新しい UNIX パスワードを再入力してください: 
passwd: パスワードは正しく更新されました
temp_user のユーザ情報を変更中
新しい値を入力してください。標準設定値を使うならリターンを押してください
    フルネーム []: temp
    部屋番号 []: 
    職場電話番号 []: 
    自宅電話番号 []: 
    その他 []: 
以上で正しいですか? [Y/n] y

temp_userにsudo権限を追加

作ったばかりのtemp_userにはsudo権限がないので temp_userでusermodをすると以下のエラーが出た

$ usermod
コマンド 'usermod' は '/usr/sbin/usermod' で利用できます
'/usr/sbin'がPATH環境変数に含まれていないためコマンドを特定できませんでした。
大抵の場合、お使いのユーザーアカウントに管理者特権がないことが原因です。
usermod: コマンドが見つかりません
temp_user@ludwig125-virtual-machine:/home$ useradd
コマンド 'useradd' は '/usr/sbin/useradd' で利用できます
'/usr/sbin'がPATH環境変数に含まれていないためコマンドを特定できませんでした。
大抵の場合、お使いのユーザーアカウントに管理者特権がないことが原因です。
useradd: コマンドが見つかりません

temp_userでusermodをできるように、予めtemp_userにsudo権限を付けておく

sudoユーザーを追加する方法 - Linux入門 - Webkaru

以下はtemp_userではなく、もとのユーザ権限で実行

 usermod -G sudo temp_user

temp_userでログインし直す

ubuntuのユーザをみて、temp_userに切り替える

temp_userでusermod実行

temp_user内で改めてusermodを実行

$ sudo usermod -l ludwig125 <今のユーザ名>
usermod: user <今のユーザ名> is currently used by process 1495
$ 

もとのユーザのプロセスが動いているので、全部killする

sudo kill -9 プロセスID

再度usermodを実行したら、今度はうまくいった

ユーザディレクトリの名前を変更

$ ls /home
$ cd /home
$ sudo mv もとのユーザ ludwig125
$ ls /home
ludwig125  temp_user

whoで確認

[~] $ who
ludwig125 :0           2017-12-16 22:42 (:0)
ludwig125 pts/5        2017-12-16 22:46 (:0:S.0)
ludwig125 pts/13       2017-12-16 22:46 (:0:S.1)
[~] $ 

更に/etc/passwdのユーザディレクトリを変える

$ sudo vim /etc/passwd
で
ludwig125:x:1000:1000:ludwig125:/home/ludwig125:/bin/bash
↑この/home以下のディレクトリ名をもとのユーザ名から変える

上記までの対応によって生じた問題

トラブル1.VMとホストOSとの間でコピペができない

名前変更後、VMのデータをコピーしてホストOSのWindowsにペーストできないという問題が生じた

ホスト名を変えてしまったのでvmwaretoolsが機能していない可能性がある

いったんVMもホストOSも再起動したらコピペができるようになった

VMware Tools の概要
VMware Tools は、仮想マシンのゲスト OS のパフォーマンスを強化し、仮想マシンの管理を改善するユーティリティのスイートです。ゲスト OS に VMware Tools をインストールしておかないと、ゲストで重要な機能を実行できません。VMware Tools をインストールすると、次のような問題が排除または改善されます。
ビデオの解像度が低い
カラー深度が不十分
ネットワーク速度の表示が正しくない
マウスの動きが制限される
コピー アンド ペーストやファイルのドラッグ アンド ドロップができない
音声が出ない
ゲスト OS の静止スナップショットを作成する機能が用意される
ゲスト OS とホストの時刻が同期される

トラブル2. linuxのグループが変わっていない

グループ名が昔のまま変わっていなかったので変える

usermod -g グループ名 ユーザ名
[/home] $ sudo groupadd ludwig125
[/home] $ sudo  usermod -g  ludwig125 ludwig125
[/home] $ 

トラブル3. git に接続できない

名前変更後、gitに接続できない

git pullできない 「Permission denied (publickey).」が出た

[~/git/work] $ git pull
Warning: Permanently added the RSA host key for IP address '192.30.255.113' to the list of known hosts.
Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
[~/git/work] $ 

以下を参考に調べて見る

githubで"Permission denied (publickey)."が出た時はssh -Tで繋ぎ直す - Qiita Error: Permission denied (publickey) - User Documentation Git - SSH 公開鍵の作成

[~/git/work] $ ssh -vT git@github.com
OpenSSH_6.6.1, OpenSSL 1.0.1f 6 Jan 2014
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 19: Applying options for *
debug1: Connecting to github.com [192.30.255.112] port 22.
debug1: Connection established.
debug1: identity file /home/ludwig125/.ssh/id_rsa type 1
debug1: identity file /home/ludwig125/.ssh/id_rsa-cert type -1
debug1: identity file /home/ludwig125/.ssh/id_dsa type -1
debug1: identity file /home/ludwig125/.ssh/id_dsa-cert type -1
debug1: identity file /home/ludwig125/.ssh/id_ecdsa type -1
debug1: identity file /home/ludwig125/.ssh/id_ecdsa-cert type -1
debug1: identity file /home/ludwig125/.ssh/id_ed25519 type -1
debug1: identity file /home/ludwig125/.ssh/id_ed25519-cert type -1
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.8
debug1: Remote protocol version 2.0, remote software version libssh_0.7.0
debug1: no match: libssh_0.7.0
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: server->client aes128-ctr hmac-sha1 none
debug1: kex: client->server aes128-ctr hmac-sha1 none
debug1: sending SSH2_MSG_KEX_ECDH_INIT
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug1: Server host key: RSA 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48
debug1: Host 'github.com' is known and matches the RSA host key.
debug1: Found key in /home/ludwig125/.ssh/known_hosts:1
debug1: ssh_rsa_verify: signature correct
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: SSH2_MSG_SERVICE_REQUEST sent
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey
debug1: Next authentication method: publickey
debug1: Offering RSA public key: /home/ludwig125/.ssh/id_rsa
debug1: Authentications that can continue: publickey
debug1: Trying private key: /home/ludwig125/.ssh/id_dsa
debug1: Trying private key: /home/ludwig125/.ssh/id_ecdsa
debug1: Trying private key: /home/ludwig125/.ssh/id_ed25519
debug1: No more authentication methods to try.
Permission denie
[~/git/work] $

ホスト名を変えたからなのか、なぜなのかわからないけれど、git にssh鍵が登録されていないみたい

以前書いた自分のブログを参考にssh鍵を作って登録し直す

ludwig125.hatenablog.com

登録後

[~/git/work] $ ssh -vT git@github.com
OpenSSH_6.6.1, OpenSSL 1.0.1f 6 Jan 2014
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 19: Applying options for *
debug1: Connecting to github.com [192.30.255.113] port 22.
debug1: Connection established.
debug1: identity file /home/ludwig125/.ssh/id_rsa type 1
debug1: identity file /home/ludwig125/.ssh/id_rsa-cert type -1
debug1: identity file /home/ludwig125/.ssh/id_dsa type -1
debug1: identity file /home/ludwig125/.ssh/id_dsa-cert type -1
debug1: identity file /home/ludwig125/.ssh/id_ecdsa type -1
debug1: identity file /home/ludwig125/.ssh/id_ecdsa-cert type -1
debug1: identity file /home/ludwig125/.ssh/id_ed25519 type -1
debug1: identity file /home/ludwig125/.ssh/id_ed25519-cert type -1
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.8
debug1: Remote protocol version 2.0, remote software version libssh_0.7.0
debug1: no match: libssh_0.7.0
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: server->client aes128-ctr hmac-sha1 none
debug1: kex: client->server aes128-ctr hmac-sha1 none
debug1: sending SSH2_MSG_KEX_ECDH_INIT
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug1: Server host key: RSA 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48
The authenticity of host 'github.com (192.30.255.113)' can't be established.
RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'github.com,192.30.255.113' (RSA) to the list of known hosts.
debug1: ssh_rsa_verify: signature correct
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: SSH2_MSG_SERVICE_REQUEST sent
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey
debug1: Next authentication method: publickey
debug1: Offering RSA public key: /home/ludwig125/.ssh/id_rsa
debug1: Server accepts key: pkalg ssh-rsa blen 279
debug1: key_parse_private2: missing begin marker
debug1: read PEM private key done: type RSA
debug1: Authentication succeeded (publickey).
Authenticated to github.com ([192.30.255.113]:22).
debug1: channel 0: new [client-session]
debug1: Entering interactive session.
debug1: Sending environment.
debug1: Sending env LANG = ja_JP.UTF-8
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
Hi ludwig125! You've successfully authenticated, but GitHub does not provide shell access.
debug1: channel 0: free: client-session, nchannels 1
Transferred: sent 3312, received 1872 bytes, in 0.2 seconds
Bytes per second: sent 14182.2, received 8016.0
debug1: Exit status 1
[~/git/work] $

成功 git pullもgit pushもできるようになった! ブログ書いててよかったよ

トラブル4. pip3が使えなくなってた

誤ったインタプリタです: そのようなファイルやディレクトリはありません

pip3を使おうとしたらこんなエラーが

[~/git/work/src/python/memo/pandas] $ pip3 install pandas_ply
/home/ludwig125/.pyenv/pyenv.d/exec/pip-rehash/pip: /home/ludwig125/.pyenv/versions/3.5.4/bin/pip3: /home/前のユーザ名/.pyenv/versions/3.5.4/bin/python3.5: 誤ったインタプリタです: そのようなファイルやディレクトリはありません

前のユーザ名のパスを見ようとしている?

解決できないのでpyenvごと削除して作り直す

[~] $ pyenv versions
* system (set by /home/ludwig125/.python-version)
  3.5.4
[~] $ pyenv uninstall 3.5.4
pyenv: remove /home/ludwig125/.pyenv/versions/3.5.4? yes
[~] $ 


[~] $  pyenv install 3.5.4
Downloading Python-3.5.4.tar.xz...
-> https://www.python.org/ftp/python/3.5.4/Python-3.5.4.tar.xz
Installing Python-3.5.4...
Installed Python-3.5.4 to /home/ludwig125/.pyenv/versions/3.5.4

$ pyenv local 3.5.4で移動

これでpip3を使えるようにになった

[~] $ 
[~] $ pip3 --version
pip 9.0.1 from /home/ludwig125/.pyenv/versions/3.5.4/lib/python3.5/site-packages (python 3.5)
[~] $ 

pythonでseleniumを使う

参考

とりあえず参考になったページを貼っておく

入門、Selenium - Seleniumの仕組み | CodeGrid

Selenium使ってみた(Python) - コンピュータサイエンス系勉強ノート

PythonでSeleniumを使ってスクレイピング (基礎) - Qiita

3秒でわかるSeleniumのつかいかた(Python・ちょっとDjango) - へっぽこびんぼう野郎のnewbie日記

Selenium使ってみた(Python) - コンピュータサイエンス系勉強ノート

準備

seleniumをインストール

$ pip3 install selenium

以下からchromedriverをダウンロード

以下のファイルを実行

$ cat selenium-test.py
from selenium import webdriver
browser = webdriver.Chrome(executable_path='/home/ludwig125/chromedriver')
browser.get('https://www.yahoo.co.jp/')

実行

python3 selenium-test.py 

Chromeが起動してyahooのページが表示される

f:id:ludwig125:20171216230538p:plain

トラブル対応

moduleが無いとかでうまく実行できなかったので、以下を確認し直す

$ sudo apt install python3-pip python3-dev

$ pyenv install 3.5.4
$ pyenv local 3.5.4
$ pyenv versions
  system
* 3.5.4 (set by /home/ludwig125/git/work/src/python/.python-version)
$ 

python3のパスを確認

$ which python3
/home/ludwig125/.pyenv/shims/python3
$ /home/ludwig125/.pyenv/shims/python3 --version
Python 3.5.4
$ 

pythonでグラフを描画

グラフの例(sin関数)

【Python入門】ライブラリmatplotlibの基本的な使い方 - Qiita

[~/git/work/src/python] $ cat test.py
import math
import numpy as np
from matplotlib import pyplot

pi = math.pi

x = np.linspace(0, 2*pi, 100)
y = np.sin(x)

pyplot.plot(x, y)
pyplot.show()
[~/git/work/src/python] $ 

実行

python3 test.py 

f:id:ludwig125:20171207010603p:plain

以下、これを表示するまでのエラー

エラー対応

参考

matplotlibが描画されない - DISTRICT 37

python - python3 で _tkinter を import したい - スタック・オーバーフロー

ImportError:
Importing the multiarray numpy extension module failed.  Most
likely you are trying to import a failed build of numpy.
If you're working with a numpy git repo, try `git clean -xdf` (removes all
files not under version control).  Otherwise reinstall numpy.

Original error was: /usr/local/lib/python2.7/dist-packages/numpy/core/multiarray.so: undefined symbo
l: _Py_ZeroStruct

[~/git/work/src/python/software-design/saikyu-kouka] $ pip3 install numpy
Traceback (most recent call last):
  File "/usr/local/bin/pip3", line 7, in <module>
    from pip import main
  File "/usr/local/lib/python3.6/site-packages/pip/__init__.py", line 26, in <module>
    from pip.utils import get_installed_distributions, get_prog
  File "/usr/local/lib/python3.6/site-packages/pip/utils/__init__.py", line 16, in <module>
    import subprocess
  File "/usr/local/lib/python3.6/subprocess.py", line 136, in <module>
    import _posixsubprocess
ImportError: /usr/local/lib/python2.7/dist-packages/_posixsubprocess.so: undefined symbol: Py_InitMo
dule4_64


や

 Traceback (most recent call last):
  File "test.py", line 3, in <module>
    from matplotlib import pyplot
  File "/usr/local/lib/python3.6/site-packages/matplotlib/pyplot.py", line 113, in <module>
    _backend_mod, new_figure_manager, draw_if_interactive, _show = pylab_setup()
  File "/usr/local/lib/python3.6/site-packages/matplotlib/backends/__init__.py", line 60, in pylab_setup
    [backend_name], 0)
  File "/usr/local/lib/python3.6/site-packages/matplotlib/backends/backend_tkagg.py", line 6, in <module>
    from six.moves import tkinter as Tk
  File "/usr/local/lib/python2.7/dist-packages/six.py", line 92, in __get__
    result = self._resolve()
  File "/usr/local/lib/python2.7/dist-packages/six.py", line 115, in _resolve
    return _import_module(self.mod)
  File "/usr/local/lib/python2.7/dist-packages/six.py", line 82, in _import_module
    __import__(name)
  File "/usr/local/lib/python3.6/tkinter/__init__.py", line 36, in <module>
    import _tkinter # If this fails your Python may not be configured for Tk
ModuleNotFoundError: No module named '_tkinter'

などのエラーが出た

もう面倒になったので、pyenvをつくって、入れ直した

$ sudo apt install python3-pip python3-dev

$ pyenv install 3.5.4
$ pyenv local 3.5.4
$ pyenv versions
  system
* 3.5.4 (set by /home/ludwig125/git/work/src/python/.python-version)
$ 

python3のパスを確認

$ which python3
/home/ludwig125/.pyenv/shims/python3
$ /home/ludwig125/.pyenv/shims/python3 --version
Python 3.5.4
$ 

追加で必要なライブラリをインストール

$ python3 -m pip install numpy
$ python3 -m pip install matplotlib

tkinterが使えることを確認

$ python3 -m tkinter

f:id:ludwig125:20171207011158p:plain

グラフの例(1次関数)

$ cat y-is-10x.py 
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 99, 100)

y = x * 10

plt.plot(x, y)
plt.show()

実行結果

 $ python3  y-is-10x.py 

f:id:ludwig125:20171207012956p:plain

グラフの例(ノイズの入った1次関数)

$ cat noisy_y.py 
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 99, 100)

f_noisy = np.vectorize(lambda x: x * 10 + np.random.normal(0, 100))
d = f_noisy(x)

plt.plot(x, d)
plt.show()

実行結果

python3 noisy_y.py 

f:id:ludwig125:20171207013117p:plain

グラフの例(放物線)

$ cat throw.py 

from math import sin, cos, radians
from matplotlib import pyplot as plt

def throw(x, y, v0, angle, repeatNum, dt):
    isSuccess = False
    xarray = []; yarray = []
    vx = v0*cos( radians(angle) )
    vy = v0*sin( radians(angle) )
    ax = 0.0
    ay = -9.8
    for i in range(repeatNum):
        x = x + (vx + ax*dt/2)*dt
        y = y + (vy + ay*dt/2)*dt
        vx = vx + ax * dt
        vy = vy + ay * dt
        xarray.append(x)
        yarray.append(y)
    return (xarray, yarray, isSuccess)

def prepareFigureArea():
    plt.figure(figsize=(5, 5))
    plt.xlim([0, 5])
    plt.ylim([0, 5])
    plt.xlabel('X - Axis (m)')
    plt.ylabel('Y - Axis (m)')
    return

x1, y1, isSuccess = throw(0, 0, 6, 35, 500, 0.01)
x2, y2, isSuccess2 = throw(0, 0, 6, 45, 500, 0.01)
x3, y3, isSuccess3 = throw(0, 0, 6, 55, 500, 0.01)
x4, y4, isSuccess3 = throw(0, 0, 6, 70, 500, 0.01)

prepareFigureArea()
plt.plot(x1, y1, 'bo-', x2, y2, 'ro-', x3, y3, 'ko-', x4, y4, 'yo-')
plt.legend(['35 deg.', '45 deg.', '55 deg.', '70 deg.'])
plt.show()

実行結果

python3 throw.py

以下が必要だったのでpip3 install

$ pip3 install six
$ pip3 install pyparsing
$ pip3 install cycler
$ pip3 install python-dateutil --upgrade

f:id:ludwig125:20171209004734p:plain

matplotlibの仕様

グラフの点や線の形

グラフの色

matplotlib参考

モンティ・ホール問題メモ

enakai00.hatenablog.com

qiita.com

MSGPACK_DEFINEが32個までしか対応していない問題

msgpackについては以下を参照

ludwig125.hatenablog.com

問題

MSGPACK_DEFINEで33個以上の引数を取ることができなかった

msgpackのバージョン

現在のmasterのバージョンは2.1.5

https://github.com/msgpack/msgpack-c/blob/master/CHANGELOG.md

MSGPACK_DEFINEとは

保存したいクラスのメンバ変数を、MSGPACK_DEFINEマクロに入れると、 自動でシリアライズ/デシリアライズできる

https://github.com/msgpack/msgpack-c/blob/master/QUICKSTART-CPP.md#user-defined-classes

You can use serialize/deserializes user-defined classes using MSGPACK_DEFINE macro.

ソースコード

MSGPACK_DEFINEの数が32のファイル

[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ cat msgpack_define_before-expand32.cpp
#include <msgpack.hpp>
#include <vector>
#include <string>
#include <iostream>

class myclass {
public:
    std::string var[32];

    MSGPACK_DEFINE(
    var[0], var[1], var[2], var[3], var[4], var[5], var[6], var[7], var[8], var[9], var[10], var[11], var[12], var[13], var[14], var[15], var[16], var[17], var[18], var[19], var[20], var[21], var[22], var[23], var[24], var[25], var[26], var[27], var[28], var[29], var[30], var[31]);
    myclass() {
        var[0] = "0";
        var[1] = "1";
        var[2] = "2";
        var[3] = "3";
        var[4] = "4";
        var[5] = "5";
        var[6] = "6";
        var[7] = "7";
        var[8] = "8";
        var[9] = "9";
        var[10] = "10";
        var[11] = "11";
        var[12] = "12";
        var[13] = "13";
        var[14] = "14";
        var[15] = "15";
        var[16] = "16";
        var[17] = "17";
        var[18] = "18";
        var[19] = "19";
        var[20] = "20";
        var[21] = "21";
        var[22] = "22";
        var[23] = "23";
        var[24] = "24";
        var[25] = "25";
        var[26] = "26";
        var[27] = "27";
        var[28] = "28";
        var[29] = "29";
        var[30] = "30";
        var[31] = "31";
}
};

int main(void) {
        std::vector<myclass> vec;
        // add some elements into vec...
        vec.push_back(myclass());

        // you can serialize myclass directly
        msgpack::sbuffer sbuf;
        msgpack::pack(sbuf, vec);

        msgpack::object_handle oh =
            msgpack::unpack(sbuf.data(), sbuf.size());

        msgpack::object obj = oh.get();

        // you can convert object to myclass directly
        std::vector<myclass> rvec;
        obj.convert(rvec);

        for(std::vector<myclass>::iterator it = rvec.begin(); it != rvec.end(); ++it) {

            for(int i = 0; i < 32; i++) {
                std::cout << (*it).var[i] << std::endl;
            }
        }
}
[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ 

コンパイルと実行結果

[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ g++ -Ipath_to_msgpack/include msgpack_define_before-expand32.cpp
[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ ./a.out 
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ 

これはできる

MSGPACK_DEFINEの数が33のファイル

上のファイルで33個目を追加するとコンパイルに失敗

コンパイルエラー抜粋

 /usr/local/include/msgpack/v1/adaptor/detail/cpp03_define_array.hpp:4468:171: note:   template argument deduction/substitution failed:
In file included from /usr/local/include/msgpack/adaptor/define.hpp:13:0,
                 from /usr/local/include/msgpack/type.hpp:25,
                 from /usr/local/include/msgpack.hpp:18,
                 from msgpack_define_before-expand33.cpp:1:
msgpack_define_before-expand33.cpp:10:5: note:   candidate expects 32 arguments, 33 provided
     MSGPACK_DEFINE(
     ^
In file included from /usr/local/include/msgpack/v1/adaptor/define.hpp:14:0,
                 from /usr/local/include/msgpack/adaptor/define.hpp:15,
                 from /usr/local/include/msgpack/type.hpp:25,
                 from /usr/local/include/msgpack.hpp:18,
                 from msgpack_define_before-expand33.cpp:1:

MSGPACK_DEFINEの定義

https://github.com/msgpack/msgpack-c/blob/315bbd4b40ba5b21bfaeced0e5b7688d833a5b91/include/msgpack/v1/adaptor/detail/cpp03_define_array.hpp#L4470

return define_array<A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23, A24, A25, A26, A27, A28, A29, A30, A31>(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31);
  • MSGPACK_DEFINEで呼んでいる関数には32個までしか対応していない

対応策

考えられる対応策は以下の3つ

  • 案1.c++11にする
  • 案2.MSGPACK_DEFINEを入れ子にする
  • 案3.拡張版のMSGPACK_DEFINEを作成する

以下詳細を説明

案1.c++11にする

c++11なら出来るらしい

msgpackの1.0以上、かつc++11だったら33個以上もできそう https://github.com/msgpack/msgpack-c/issues/11

for c++98, we can't extend it easily, all we can do is just write extra specialization for more args. but for c++11, we can use variadic template to break it, although, there is limit, but it's compiler's business.

これができるならそれで問題ない

c++11でコンパイルが通ることを確認

上でコンパイルエラーになったmsgpack_define_before-expand33.cppをc++11でコンパイル

[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ g++ -Ipath_to_msgpack/include -std=c++11 msgpack_define_before-expand33.cpp
[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ ./a.out 
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ 

案2.MSGPACK_DEFINEを入れ子にする

  • 例えば、stuct Aに33個以上の項目を入れてまとめてMSGPACK_DEFINEをしようとすると失敗する
  • そこで、別にstruct Bを用意して、その中に項目を入れて、MSGPACK_DEFINEし、さらにそのstructBをstructAの一要素とすれば(入れ子にすれば)、それぞれのstructの項目数は32個を超えずに済む
  • 多分これでもできそうだが、入れ子になるのが気持ち悪かったので試してない

案3.拡張版のMSGPACK_DEFINEを作成する

  • msgpack 0.5ではかんたんだったけど、最新版は難しい

手順1.拡張版ファイルの作成

https://github.com/msgpack/msgpack-c/tree/315bbd4b40ba5b21bfaeced0e5b7688d833a5b91/erb/v1

ここのerbのGENERATION_LIMIT = 31を40とかに書き換える

https://github.com/msgpack/msgpack-c/blob/315bbd4b40ba5b21bfaeced0e5b7688d833a5b91/erb/v1/cpp03_define_array.hpp.erb#L24

今回上のソースコードで使っているのはarrayだけなので、arrayとそこでつかっているtupleだけ増やしたファイルを用意すればいい(mapは不要) なので、以下のファイルのLIMITを40とかに書き換える

  • cpp03_msgpack_tuple_decl.hpp.erb
  • cpp03_msgpack_tuple.hpp.erb
  • cpp03_define_array_decl.hpp.erb
  • cpp03_define_array.hpp.erb

あとは、以下のファイルを実行すれば、修正したerbをもとに拡張版のヘッダファイルが自動で作成される

https://github.com/msgpack/msgpack-c/blob/315bbd4b40ba5b21bfaeced0e5b7688d833a5b91/preprocess

rubyが無いと言われたので以下でインストール

http://kwski.net/linux/1223/

# apt-add-repository ppa:brightbox/ruby-ng  // レポジトリの追加
# apt-get update                            // 
# apt-get install ruby2.2                   // ruby(バージョン)のインストール

手順2.作ったファイルでライブラリのファイルを置き換える

これで作ったファイルを実際のmsgpackファイルと置き換える

  • 以下のファイルをつくったファイルと置き換える
    • /usr/local/include/msgpack/v1/adaptor/detail

これで実行すると、拡張版を使って33以上の項目もMSGPACK_DEFINEできる

[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ cat msgpack_define_expand33.cpp
#include <msgpack.hpp>
#include <vector>
#include <string>
#include <iostream>

class myclass {
public:
    std::string var[33];

    MSGPACK_DEFINE(
    var[0], var[1], var[2], var[3], var[4], var[5], var[6], var[7], var[8], var[9], var[10], var[11], var[12], var[13], var[14], var[15], var[16], var[17], var[18], var[19], var[20], var[21], var[22], var[23], var[24], var[25], var[26], var[27], var[28], var[29], var[30], var[31], var[32]);
    myclass() {
        var[0] = "0";
        var[1] = "1";
        var[2] = "2";
        var[3] = "3";
        var[4] = "4";
        var[5] = "5";
        var[6] = "6";
        var[7] = "7";
        var[8] = "8";
        var[9] = "9";
        var[10] = "10";
        var[11] = "11";
        var[12] = "12";
        var[13] = "13";
        var[14] = "14";
        var[15] = "15";
        var[16] = "16";
        var[17] = "17";
        var[18] = "18";
        var[19] = "19";
        var[20] = "20";
        var[21] = "21";
        var[22] = "22";
        var[23] = "23";
        var[24] = "24";
        var[25] = "25";
        var[26] = "26";
        var[27] = "27";
        var[28] = "28";
        var[29] = "29";
        var[30] = "30";
        var[31] = "31";
        var[32] = "32";
}
};

int main(void) {
        std::vector<myclass> vec;
        // add some elements into vec...
        vec.push_back(myclass());

        // you can serialize myclass directly
        msgpack::sbuffer sbuf;
        msgpack::pack(sbuf, vec);

        msgpack::object_handle oh =
            msgpack::unpack(sbuf.data(), sbuf.size());

        msgpack::object obj = oh.get();

        // you can convert object to myclass directly
        std::vector<myclass> rvec;
        obj.convert(rvec);

        for(std::vector<myclass>::iterator it = rvec.begin(); it != rvec.end(); ++it) {

            for(int i = 0; i < 33; i++) {
                std::cout << (*it).var[i] << std::endl;
            }
        }
}
[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ 

コンパイルと実行

[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ g++ -Ipath_to_msgpack/include msgpack_define_expand33.cpp
[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ ./a.out 
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32  ← 33個目が使えている!
[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $