c++でmsgpackを使ってみる
msgpackとは
MessagePack: It's like JSON. but fast and small.
MessagePackは、効率の良いバイナリ形式のオブジェクト・シリアライズ フォーマットです。 JSONの置き換えとして使うことができ、様々なプログラミング言語をまたいでデータを交換することが可能です。 しかも、JSONよりも速くてコンパクトです。 例えば、小さな整数値はたった1バイト、短い文字列は文字列自体の長さ+1バイトでシリアライズできます。
らしい
仕事で使う機会があったのでc++でサンプルコードを実行してみる
msgpackのインストール
MessagePack: It's like JSON. but fast and small. → C/C++ msgpack のページに従う
準備
` インストール条件
gcc >= 4.1.0 cmake >= 2.8.0
gccバージョン確認
$ g++ -v Using built-in specs. COLLECT_GCC=g++ COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04.3' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3)
cmake確認
なかったのでインストール
sudo apt-get install cmake $ cmake -version cmake version 2.8.12.2
msgpackのインストール
msgpackのgitはここ
$ git clone https://github.com/msgpack/msgpack-c.git $ cd msgpack-c $ cmake . $ make $ sudo make install
msgpackのバージョンを確認
- 現在のmasterのバージョンは2.1.5らしい
- msgpack-c/CHANGELOG.md at master · msgpack/msgpack-c · GitHub
msgpackのサンプルコードを実行
msgpack-c/QUICKSTART-CPP.md at master · msgpack/msgpack-c · GitHub
First program(単なるデータのシリアライズとデシリアライズ)
コード
以下を hello.cpp という名前で保存
#include <msgpack.hpp> #include <vector> #include <string> #include <iostream> int main(void) { // serializes this object. std::vector<std::string> vec; vec.push_back("Hello"); vec.push_back("MessagePack"); // serialize it into simple buffer. msgpack::sbuffer sbuf; msgpack::pack(sbuf, vec); // deserialize it. msgpack::object_handle oh = msgpack::unpack(sbuf.data(), sbuf.size()); // print the deserialized object. msgpack::object obj = oh.get(); std::cout << obj << std::endl; //=> ["Hello", "MessagePack"] // convert it into statically typed object. std::vector<std::string> rvec; obj.convert(rvec); }
コンパイル
$ g++ -Ipath_to_msgpack/include hello.cpp -o hello 実行 $ ./hello ["Hello", "MessagePack"]
Streaming into an array or map(配列やマップのシリアライズとデシリアライズ)
msgpack-c/QUICKSTART-CPP.md at master · msgpack/msgpack-c · GitHub
ここにはシリアライズはあるが、デシリアライズの処理がないので、自分で作ってみる
$ cat stream.cpp #include <msgpack.hpp> #include <iostream> #include <string> #include <sstream> int main(void) { // serializes multiple objects into one message containing an array using msgpack::packer. msgpack::sbuffer buffer; msgpack::packer<msgpack::sbuffer> pk(&buffer); pk.pack_array(4); pk.pack(std::string("Log message ... 1")); pk.pack(std::string("Log message ... 2")); pk.pack(std::string("Log message ... 3")); pk.pack(std::string("Log message ... 4")); // serializes multiple objects into one message containing a map using msgpack::packer. msgpack::sbuffer buffer2; msgpack::packer<msgpack::sbuffer> pk2(&buffer2); pk2.pack_map(2); pk2.pack(std::string("x")); pk2.pack(3); pk2.pack(std::string("y")); pk2.pack(3.4321); // pk2.pack(4); /*---- 以下自作部分 ----*/ // unpack array msgpack::unpacked msg; msgpack::unpack(msg, buffer.data(), buffer.size()); msgpack::object obj = msg.get(); msgpack::object_array obj_array = obj.via.array; std::string str[4]; for (int i = 0; i < 4; i++) { (obj_array.ptr[i]).convert(str[i]); std::cout << "str[" << i << "]: " << str[i] << std::endl; } // unpack map msgpack::unpacked msg2; msgpack::unpack(msg2, buffer2.data(), buffer2.size()); msgpack::object obj2 = msg2.get(); msgpack::object_map obj_map = obj2.via.map; for (int i = 0; i < 2; i++) { std::string map_key; //std::cout << "key: " << obj_map.ptr[i].key; (obj_map.ptr[i].key).convert(map_key); // 以下、mapのvalの方は、intの場合とfloatの場合があるので一旦floatにconvert // してからstringに変換した float f; // obj_map.ptr[i].valはmsgpackのobject // 一旦floatにconvertしてからそれを文字列に変換した (obj_map.ptr[i].val).convert(f); std::stringstream ss; ss << f; std::cout << "key: " << map_key << " val: " << ss.str() << std::endl; // これを実行するとintは2, floatは4と表示される //std::cout << "type: " << (obj_map.ptr[i].val).type << std::endl; // 以下のようなif文で判定できるが、このプログラムでは一括してfloatに変換している //if ( (obj_map.ptr[i].val).type == msgpack::type::POSITIVE_INTEGER ) { //} } // $ g++ -Ipath_to_msgpack/include stream.cpp -o stream }
実行結果
$ g++ -Ipath_to_msgpack/include stream.cpp -o stream $ ./stream str[0]: Log message ... 1 str[1]: Log message ... 2 str[2]: Log message ... 3 str[3]: Log message ... 4 key: x val: 3 key: y val: 3.4321
上の修正は以下を参考にした
msgpackのオブジェクトとしてここを参考にした
- https://github.com/msgpack/msgpack-c/blob/master/include/msgpack/object.h#L27-L43
- 以下でobjectのtypeが定義されているらしい
MSGPACK_OBJECT_NIL = 0x00, MSGPACK_OBJECT_BOOLEAN = 0x01, MSGPACK_OBJECT_POSITIVE_INTEGER = 0x02, MSGPACK_OBJECT_NEGATIVE_INTEGER = 0x03, MSGPACK_OBJECT_FLOAT32 = 0x0a, MSGPACK_OBJECT_FLOAT64 = 0x04, MSGPACK_OBJECT_FLOAT = 0x04, #if defined(MSGPACK_USE_LEGACY_NAME_AS_FLOAT) MSGPACK_OBJECT_DOUBLE = MSGPACK_OBJECT_FLOAT, /* obsolete */ #endif /* MSGPACK_USE_LEGACY_NAME_AS_FLOAT */ MSGPACK_OBJECT_STR = 0x05, MSGPACK_OBJECT_ARRAY = 0x06, MSGPACK_OBJECT_MAP = 0x07, MSGPACK_OBJECT_BIN = 0x08, MSGPACK_OBJECT_EXT = 0x09
- 注意点として、msgpackのバージョンによるのか、関数名や引数が参照渡しかポインタ渡しかなどが違うみたい
- 単純に例と同じようにやってもうまく行かなかった
User-defined classes(MSGPACK_DEFINE)
msgpack-c/QUICKSTART-CPP.md at master · msgpack/msgpack-c · GitHub
You can use serialize/deserializes user-defined classes using MSGPACK_DEFINE macro.
とある通り、ユーザ定義のクラスをMSGPACK_DEFINEというマクロを使ってシリアライズ/デシリアライズできる
$ cat msgpack_define.cpp #include <msgpack.hpp> #include <vector> #include <string> #include <iostream> class myclass { //private: // std::string m_str; // std::vector<int> m_vec; public: std::string m_str; std::vector<int> m_vec; MSGPACK_DEFINE(m_str, m_vec); myclass() { m_str = "default"; m_vec.push_back(1); m_vec.push_back(2); m_vec.push_back(3); } }; 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) { std::cout << (*it).m_str << std::endl; for(std::vector<int>::iterator m_vec_it = (*it).m_vec.begin(); m_vec_it != (*it).m_vec.end(); ++m_vec_it) { std::cout << (*m_vec_it) << std::endl; } } }
実行結果
$ g++ -Ipath_to_msgpack/include msgpack_define.cpp -o msgpack_define $ ./msgpack_define default 1 2 3
MSGPACK_DEFINEの定義
v1_1_cpp_adaptor · msgpack/msgpack-c Wiki · GitHub
ソースコードは以下 - https://github.com/msgpack/msgpack-c/blob/55b51c506fee9ce496e9b98aca33cadade681479/include/msgpack/adaptor/define_decl.hpp#L28-L42
#define MSGPACK_DEFINE_ARRAY(...) \ template <typename Packer> \ void msgpack_pack(Packer& pk) const \ { \ msgpack::type::make_define_array(__VA_ARGS__).msgpack_pack(pk); \ } \ void msgpack_unpack(msgpack::object const& o) \ { \ msgpack::type::make_define_array(__VA_ARGS__).msgpack_unpack(o); \ }\ template <typename MSGPACK_OBJECT> \ void msgpack_object(MSGPACK_OBJECT* o, msgpack::zone& z) const \ { \ msgpack::type::make_define_array(__VA_ARGS__).msgpack_object(o, z); \ } 同じソースコードに下に以下も定義されているので、MSGPACK_DEFINE がMSGPACK_DEFINE_ARRAYに置き換わる #define MSGPACK_DEFINE MSGPACK_DEFINE_ARRAY
pythonトラブル対応
エラー
AttributeError
AttributeError: module 'json' has no attribute 'dump'
- pythonのソースコードの中でimport jsonをしていたが、このファイル自体がjson.pyという名前だったのでモジュール名とぶつかっていたらしい
- json.py → 適当な別の名前にして解決した
- 参考:Python でモジュール利用時に AttributeError が出た時はファイル名ディレクトリ名が被ってないか調べること - shouhの日記
誤ったインタプリタです: そのようなファイルやディレクトリはありません
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: 誤ったインタプリタです: そのようなファイルやディレクトリはありません
Ubuntu14.0.4でホスト名とユーザ名を変更する - ludwig125のブログ
これでユーザ名を変えてしまったせいみたい
解決できないので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) [~] $
Ubuntu14.0.4でGoogleChromeが起動しない
問題
VMのUbuntuでChromeをアップデートしたあとで、 Google Chromeのアイコンを押しても起動しなくなってしまった
$ google-chrome [11644:11689:1103/213846.450610:FATAL:nss_util.cc(632)] NSS_VersionCheck("3.26") failed. NSS >= 3.26 is required. Please upgrade to the latest NSS, and if you still get this error, contact your distribution maintainer. 中止 (コアダンプ)
解決方法
これらを参考にパッケージをアップグレード
sudo apt-get upgrade sudo apt-get update
これで開けるようになった
[shingo-virtual-machine ~/git/work] $ google-chrome ATTENTION: default value of option force_s3tc_enable overridden by environment. ATTENTION: default value of option force_s3tc_enable overridden by environment. [18255:18293:1103/215655.013441:ERROR:simple_version_upgrade.cc(164)] File structure does not match the disk cache backend. [18255:18293:1103/215655.014000:ERROR:simple_backend_impl.cc(659)] Simple Cache Backend: wrong file structure on disk: /home/shingo/.cache/google-chrome/Default/Cache [18255:18255:1103/215655.772279:ERROR:account_tracker.cc(328)] OnGetTokenFailure: Invalid credentials. [18255:18255:1103/215655.779440:ERROR:account_tracker.cc(328)] OnGetTokenFailure: Invalid credentials. Ubuntuのパスワードを求められたので入力したら解決
apt-get参考
VMのUbuntuにWebサーバを立てる
概要
- 色々苦戦したのでメモ
やったこと
- 2.VM内のブラウザで localhost:8181 → 当然見られる
- 3.ホストPCのWindowsのブラウザで、VMのプライベートIPアドレスを指定して192.168.19.137:8181を見る → これも見られる
- 4.しかしiphoneからはアクセスできない
- 5.ルータのネットワーク外からポート8181のアクセスが来た時に、VMのWebサーバに行くようにポートフォワード(ポート開放)する
- 6.ルータがポートフォワードできるIPアドレスの範囲がVMのIPアドレスと違うー
- 7.なので、VMのIPアドレスをポートフォワードできるものに変更
- 8.ファイアウォールの設定も変更しよう ⇒ ufwで8181のポートをallowに
- 9.まだつながらない → 面倒だから 自宅ルータから直接VMをブリッジで接続しよう
- 10.出来た iphoneやノートPCのブラウザからUbuntu内のファイルの情報が見られた
- 11.グローバルIPアドレスを設定して見られないか確認
ここまで2,3日
手順
1.VM上のubuntuで pythonで簡易的にweb serverを立ち上げる ポート8181
python3の入っている環境で以下の通り、Webサーバ立ち上げる
ポートは8181
$ python3 -m http.server --cgi 8181 Serving HTTP on 0.0.0.0 port 8181 (http://0.0.0.0:8181/) ...
2.VM内のブラウザで localhost:8181 → 当然見られる
3.ホストPCのWindowsのブラウザで、VMのプライベートIPアドレスを指定して192.168.19.137:8181を見る → これも見られる
Windows側のブラウザでは上のlocalhostの部分をVMのIPアドレスにしたものを表示 - VMのIPアドレスはifconfigで取得した(IPV4のもの)
4.しかしiphoneからはアクセスできない
みられない
会社PCからも見られない
pingもtracerouteもVMのアドレスに対してやってもtimeoutする(ホストPCであるWindowsのIPアドレスに対しては問題なし)
$ ping 192.168.19.137 PING 192.168.19.137 (192.168.19.137): 56 data bytes ping: sendto: Host is down ping: sendto: Host is down Request timeout for icmp_seq 0 ping: sendto: Host is down Request timeout for icmp_seq 1 ping: sendto: Host is down Request timeout for icmp_seq 2 $ traceroute -v 192.168.19.137 traceroute to 192.168.19.137 (192.168.19.137), 64 hops max, 52 byte packets 1 * *^C
なぜつながらないのか?
あとからもう少しわかることだったが、ここで繋がらなかった理由はこの時点のVMのネットワークの設定がNATになっていて、ホストPC側の設定が正しくなかったからかもしれない
5.ルータのネットワーク外からポート8181のアクセスが来た時に、VMのWebサーバに行くようにポートフォワード(ポート開放)する
家のルータはソフトバンク光の 光BBユニット(EWMTA2.3)だった
参考
ルータの設定
そうしたら以下のように言われた
転送先IPアドレスに誤りがあります。IPアドレスの範囲内で半角数字で入力してください
6.ルータがポートフォワードできるIPアドレスの範囲がVMのIPアドレスと違うー
以下によると、転送先のIPアドレスの範囲が限られているらしく、VMのアドレスと異なるので転送できない・・・
ルータの設定
7.なので、VMのIPアドレスをポートフォワードできるものに変更
以下の方法でVMのIPアドレスを、ポート開放できる範囲に変える
実践初級ITブログ VMwareのUbuntuを固定IPにする
もともとのUbuntu IPアドレス 192.168.19.137 ブロードキャストアドレス 192.168.19.255 サブネットマスク 255.255.255.0 デフォルトルート 192.168.19.2 第一DNS 192.168.19.2 VMのUbuntuのIPを以下に変更 192.168.3.11
変える前
変えた後
ifconfigなどでIPアドレスが変わっていることを確認 再度ポート転送を設定すると成功
8.ファイアウォールの設定も変更しよう ⇒ ufwで8181のポートをallowに
utfいじる
- ここでallowにしたポート以外はファイアウォールが有効なので、ホストOSからは接続できない
第76回 Ubuntuのソフトウェアファイアウォール:UFWの利用(1):Ubuntu Weekly Recipe|gihyo.jp … 技術評論社
$ sudo ufw status 状態: 非アクティブ $ sudo ufw enable ファイアウォールはアクティブかつシステムの起動時に有効化されます。 $ sudo ufw status 状態: アクティブ $ $ sudo ufw default DENY デフォルトの incoming ポリシーは 'deny' に変更しました (適用したい内容に基づいて必ずルールを更新してください) $ sudo ufw allow 8181 ルールを追加しました ルールを追加しました (v6) $ sudo ufw status 状態: アクティブ To Action From -- ------ ---- 8181 ALLOW Anywhere 8181 (v6) ALLOW Anywhere (v6) $ sudo ufw allow http ルールを追加しました ルールを追加しました (v6)
9.まだつながらない → 面倒だから 自宅ルータから直接VMをブリッジで接続しよう
- ブリッジについて参考
以下の方法でブリッジに変更した - VMware上のLinux Webサーバに外部からアクセスできるようにする | あみだがみねのもろもろ備忘録
最初はNATに設定されていた
ブリッジに変更
よくよく考えると、VMのネットワークをブリッジ接続にしたので、ゲートウェイとDNS サーバーのIPアドレスはルータのIPアドレスが正しいはず なのに、それらがVMのIPアドレスを変える前のままになっている 以下は間違い
以下が正しい
10.出来た ! iphoneやノートPCのブラウザからUbuntu内のファイルの情報が見られた
11.グローバルIPアドレスを設定して見られないか確認
上の接続はあくまで同一ネットワーク内からVMのプライベートIPアドレス 192.168.3.11 に繋いだだけだった
自分のグローバルIPアドレスが何か? - ルータの設定が書かれた以下のWAN側IPアドレスでも見られる - http://172.16.255.254/settei.html
- 以下のサイトでも考えられる
LAN外のネットワークからルータのグローバルIPアドレスを設定して、 グローバルIP:8181で外からも接続できるか確認
- Ubuntu側でWebサーバを立てる
$python3 -m http.server --cgi 8181 (git)-[master] Serving HTTP on 0.0.0.0 port 8181 (http://0.0.0.0:8181/) ...
ネットワーク外からアクセスする
図で書くとこんな感じだと思う(間違っていないはず・・)
pythonメモ
準備
コード規約
pipインストール参考
pyenv
- システムへインストールされているバージョンとは異なるバージョンを使用したい、2系ではなく3系を使用したいなど、そういったケースではpyenvを利用する
インストール方法
- pyenvの使い方とインストール - Python入門から応用までの学習サイト
- 前提:OSはUbuntu 14.04
必要なライブラリインストール $ sudo apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev \ libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils pyenvのインストール $ git clone https://github.com/yyuu/pyenv.git ~/.pyenv $ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc $ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc $ echo 'eval "$(pyenv init -)"' >> ~/.bashrc パスの再読込 exec $SHELL
pyenvの確認
$ pyenv install -l Available versions: 2.1.3 2.2.3 2.3.7 2.4 2.4.1 2.4.2 多いので省略
- 3.5.4をインストール
$ 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/ユーザ名/.pyenv/versions/3.5.4
- バージョン確認
$ pyenv versions * system (set by /home/ユーザ名/.pyenv/version) 3.5.4
- バージョン切り替え
$ pyenv shell 3.5.4 $ pyenv versions system [ * 3.5.4 (set by PYENV_VERSION environment variable)
pyenv local 3.5.4で環境を切り替えても、その上のディレクトリには適用されていないようだった(要確認)
- pyenv環境の削除
$ pyenv uninstall 3.5.4 pyenv: remove /home/ludwig125/.pyenv/versions/3.5.4? yes $
環境変数
os.getenv
os.getenv(varname[, value])
os.environ
- 環境変数を追加
- http://tmlife.net/programming/python/python-environ.html
- env.rolesdef ← fabric
- 参考:http://a3no.hatenablog.com/entry/2014/01/24/232219
例 「host101, host201, host301, host401」 「host_role」というkeyのroleに上記のサーバを登録した場合、roleに登録されたサーバの確認方法は以下のようにする for role in env.roledefs.keys(): print env.roledefs[role] →実行結果 ['host101', 'host201', 'host301', 'host401']
文法
リスト(配列)
data = [] for i in range(1, 6): data.append(i * 2) print data
リスト内包表記
data2 = [i * 2 for i in range(1, 6)] print data2
map
mapは配列の各要素に対して関数を実行する
以下はmap(関数, 配列)
data3 = map(lambda x : x*2, range(1, 6)) print data3
実行結果
$ python list.py [2, 4, 6, 8, 10] [2, 4, 6, 8, 10] [2, 4, 6, 8, 10]
リスト内包表記
- 10以下の奇数を作成する
- リスト内包表記 のあとにif文でフィルタリングできる
>>> [ i for i in range(1, 11) if((i % 2) == 1)] [1, 3, 5, 7, 9]
python デコレータ
デコレータ例
- 関数が実行にかかった時間を表示するデコレータ
import time def time_log(func): def wrapper(*args, **kwargs): print("start: " + func.__name__) start_time = time.time() res = func(*args, **kwargs) end_time = time.time() print("end: " + func.__name__ , " elapsed time:" + str(end_time - start_time)) return res return wrapper @time_log def func1(): print("Boys, be ambitious") time.sleep(3) print("Girls, be ambitious") func1()
実行結果
$ python deco_time.py start: func1 Boys, be ambitious Girls, be ambitious ('end: func1', ' elapsed time:3.00378608704')
serial
どんなタスクも serial を指定すると設定を無視してシリアルで実行します。 http://fabric-ja.readthedocs.org/ja/latest/usage/parallel.html
roles
- ホストリストを参照するために利用されるロール名のリストを定義するデコレーター
- http://fabric-ja.readthedocs.org/ja/latest/api/core/decorators.html
- http://www.ianlewis.org/jp/fabric-pythonic
正規表現
match
文字列のエスケープとmatch - http://python-doc-ja.readthedocs.org/en/latest/howto/regex.html
ホスト名からホスト番号を取り出す
- 参考:
例: ホスト名:host022101.co.jp → 022101を取り出す host = "adsearch022101.co.jp" pattern = r"([a-z]*)(\d*)" m = re.match(pattern, host) host_num = m.group(2) print host_num ⇒ 022101
辞書
- http://www.gesource.jp/programming/python/code/0018.html
- http://www.python-izm.com/contents/basis/dict.shtml
Tips
一つの長い行を途中で折り返す 方法1.バックスラッシュ「\」を使う test = '%s \ %s' % ("aaa", "bbb") ただしこれだと 折り返した後の行頭からの空白が出力されてしまう >>> test = '%s \ ... %s' % ("aaa", "bbb") >>> print test aaa bbb 方法2.括弧で囲う test2 = ('%s ' '%s' % ("aaa", "bbb")) これなら余計なスペースは入らない >>> test2 = ('%s ' ... '%s' % ("aaa", "bbb")) >>> print test2 aaa bbb これでも大丈夫 test2 = ('%s ' '%s' % ("aaa", "bbb")) >>> test2 = ('%s ' ... '%s' ... % ("aaa", "bbb")) >>> print test2 aaa bbb
GUI
参考:実践力を身につける Pythonの教科書 | マイナビブックス
Tkinter
import tkinter.messagebox as mb ans = mb.askyesno("question", "Do you like nooble")
実行
$ python3 dialog.py
最初失敗
$ python3 dialog.py Traceback (most recent call last): File "dialog.py", line 1, in <module> import tkinter.mesagebox as mb 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'
- matplotlibが描画されない - DISTRICT 37 を参考に以下を実行
$ sudo apt install python-tk tk-dev $ pyenv install 3.5.1
再度実行
$ python3 dialog.py
あとでまたできなくなったので、改めて確認
Webサーバを立てる
参考:実践力を身につける Pythonの教科書 | マイナビブックス
pythonでWebサーバを起動
8181ポートでWebサーバを起動してみる
python3 -m http.server --cgi 8181
詳細はこちらに記載
Webサーバとして、URLのパラメータの値を取得する
参考:実践力を身につける Pythonの教科書 | マイナビブックス
chap5/5-2/cgi-bin] $ cat show-params.py #!/usr/bin/env python3 import cgi # header print("Content-Type: text/html; charset=utf=8") print("") print("<pre>") # URLパラメータを取得する form = cgi.FieldStorage() # 特定のパラメータを取得して表示 mode = form.getvalue("mode", default="") print("mode=", mode) # すべてのパラメータを取得して表示 print("--- all params ---") for k in form.keys(): print(k, "=", form.getvalue(k))
cgi-binより上のパスでWebサーバ起動
chap5/5-2] $ python3 -m http.server --cgi 8181 Serving HTTP on 0.0.0.0 port 8181 (http://0.0.0.0:8181/) ... 192.168.3.2 - - [31/Oct/2017 23:51:32] "GET /cgi-bin/show-params.py?mode=test&n=30&q=500 HTTP/1.1" 200 -
インスタンス
クラスのオーバーロード
class Pos: def __init__(self, x, y): self.x = x self.y = y def __add__(self, other): x2 = self.x + other.x y2 = self.y + other.y return Pos(x2, y2) def add(self, other): # オーバーロードではなく関数呼び出しで同じ結果を得ることができるか・・? x2 = self.x + other.x y2 = self.y + other.y return Pos(x2, y2) def __str__(self): return "{0}, {1}".format(self.x, self.y) p1 = Pos(10, 20) p2 = Pos(100, 400) p3 = p1 + p2 # +演算子をオーバーロードした__add__を使う print(p3) p3 = p1.add(p2) # 上記のp1 + p2 はこれと同じこと print(p3)
結果
$ python3 pos-add2.py 110, 420 110, 420
テスト
unittest
- https://docs.python.jp/3/library/unittest.html
- http://docs.python.jp/2/library/unittest.html#unittest.TestCase.assertRaises
- http://www.yoheim.net/blog.php?q=20160902
pytest
- 参考:Python testing 勉強会(1) pytestを使ってみる
インストール flake8入れる flake8 sudo easy_install-2.7 flake8 pip入れる pip sudo easy_install-2.7 pip pytest入れる sudo pip install pytest
pytest実行
-v
pytestに「-v」を付けると差分が詳細表示される --caputure=no --caputure=no でテスト中のprint文などを出力する
monkeypatch
http://thinkami.hatenablog.com/entry/2017/03/07/065903 https://docs.pytest.org/en/latest/monkeypatch.html http://niwaringo.tumblr.com/post/66948561978/pytest%E3%81%AEmonkeypatch%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6urllibrequest%E3%81%AE%E3%83%A6%E3%83%8B%E3%83%83%E3%83%88%E3%83%86%E3%82%B9%E3%83%88%E3%82%92%E3%81%99%E3%82%8B