Pythonのunittestとcoverage
PythonのUnit Testとカバレッジ計測のメモです。
Pythonの標準的なUnit Testフレームワークとして、unittestがあります。 テストの書き方はいわゆるxUnitとよく似ています。
テスト対象のサンプルクラスuser.pyです。2つのメソッドを定義しています。
class User: def __init__(self, name, email): self.__name = name self.__email = email def __str__(self): return '[' + self.__name + ', ' + self.__email + ']' def get_name(self): return self.__name def get_email(self): return self.__email
そしてunittestを使ったコードtest_user.pyです。Userの2つのメソッドについてテストを書いています。
import unittest from user import User class TestUser(unittest.TestCase): def setUp(self): self._user = User('taro', 'taro@example.com') def test_get_name(self): self.assertEqual('taro', self._user.get_name()) def test_get_email(self): self.assertEqual('taro@example.com', self._user.get_email()) if __name__ == '__main__': unittest.main()
以下のようにテストを実行できます(python test_user.py
と直接実行してもOK)
$ python -m unittest test_user .. ---------------------------------------------------------------------- Ran 2 tests in 0.000s OK
次はカバレッジです。カバレッジを計測するツールとして、coverageがあります。
http://blanktar.jp/blog/2015/03/python-unittest-coverage.html
pipでインストール後、coverage run
コマンドでunittestのテストケースを走らせます。
$ coverage run test_user.py .. ---------------------------------------------------------------------- Ran 2 tests in 0.000s OK
カバレッジ測定結果が.coverage
に生成されます。それをhtmlに変換して、ブラウザで見てみます。
$ coverage html user.py $ open htmlcov/index.html
ファイルごとの実行割合がまず一覧で表示されます。ここでは1ファイルしかありませんが。
ファイル名をクリックすると、そのファイルで実行されなかった文が一目でわかります。いい感じです。
PythonのrequestsでmultipartでPOST
PythonのHTTP clientとしてrequestsという便利なライブラリがあります。それをつかってMultipartデータをPOSTするメモです。
POSTするデータは、(ファイル名, データ, Content-Type)
あるいは(ファイル名, データ, Content-Type, ヘッダー)
というタプルで与えます。
クライアントからname, email, imageを送信する例です。
>>> import requests >>> r = requests.post("http://localhost:8080/add", files = { "name": ("", "hoge", "text/plain; charset=UTF-8"), "email": ("", "hoge@example.com", "plain/text; charset=UTF-8"), "image": ("hoge.png", open('hoge.png', 'rb'), "image/png") })
サーバー側での受信結果。ファイル名を空にすると、multipartの各要素のfilenameプロパティが与えられません。
--0a3d87b93d8c468b9b4dc7a493fbeee3 Content-Disposition: form-data; name="image"; filename="hoge.png" Content-Type: image/png ..................<image data>............................. --0a3d87b93d8c468b9b4dc7a493fbeee3 Content-Disposition: form-data; name="name" Content-Type: text/plain; charset=UTF-8 hoge --0a3d87b93d8c468b9b4dc7a493fbeee3 Content-Disposition: form-data; name="email" Content-Type: plain/text; charset=UTF-8 hoge@example.com --0a3d87b93d8c468b9b4dc7a493fbeee3--
OpenCV 3でPythonからSIFT
OpenCV 3では、ライセンスやパテント上の理由だろうか、SIFTやSURFはopencv_contribという別モジュールに分かれてしまっている。
opencv_contribを使うには、インストールの際に--with-contrib
オプションを付ける必要があるようだ。Mac OSだとHomebrewで以下のようにインストールできる。
brew install python brew install opencv3 --with-contrib brew link opencv3 --force
これでSIFTが使えるようになる。
# -*- coding: utf-8 -*- import cv2 def main(): img = cv2.imread('image.jpg', 0) # detector = cv2.FeatureDetector_create('ORB') detector = cv2.xfeatures2d.SIFT_create() keypoints = detector.detect(img) out = cv2.drawKeypoints(img, keypoints, None) cv2.imshow('sift', out) cv2.waitKey(0) if __name__ == '__main__': main()
玉音放送をMacからGET
Dockerの使い方
Dockerの使い方について調べたことをメモします。
インストールと起動
sudo yum install docker sudo chkconfig docker on sudo service docker start
以降の操作は全てrootで行うと仮定。
イメージの取得
pull
コマンドでイメージを取得する。
# docker pull centos:6.6
ここではcentosの6.6のイメージを指定している。イメージは、レポジトリとタグにより指定される。centosがリポジトリで、6.6がタグである。
デフォルトでは、Docker Hubという「レジストリ」からイメージを取得することになっている。
レジストリにどのようなリポジトリがあるかは、searchコマンドで検索できる。ただしタグは検索できない。
# docker search <search-keyword>
イメージ一覧の表示
images
コマンドでイメージがダウンロードされていることを確認する。
# docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE centos 6.6 8b44529354f3 2 weeks ago 202.6 MB
コンテナの起動
run
コマンドでイメージと何らかのコマンドを指定することで、コンテナが起動する。ここではコマンドとしてbash
を起動する。
# docker run -ti centos:6.6 /bin/bash
-t
は仮想端末を割り当てるオプション、-i
はSTDINを開いたままにするオプションで、シェルのようにインタラクティブに操作する場合はいずれも必須。
コンテナの中で操作
コンテナでhttpdをインストールしてみる。
# docker run -ti centos:6.6 /bin/bash [root@11dd19074528 /]# yum install -y httpd [root@11dd19074528 /]# echo 'hello world' > /var/www/html/index.html [root@11dd19074528 /]# exit
exitすると/bin/bashが死んでコンテナが停止する。しかしコンテナが停止しても、httpdのインストールがなされた状態のままで残る。どのようなコンテナが残っているのかは、docker ps -a
コマンドで確認できる。
# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 11dd19074528 centos:6.6 "/bin/bash" About a minute ago Exited (0) 5 seconds ago condescending_shockley
イメージ化
コンテナをイメージとして保存(commit)することで、後に使いまわせるようになる。ここではcentos:httpd_installedというイメージ名でイメージ化する。
# docker commit -m 'install httpd' <image-id> centos:httpd_installed # docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE centos httpd_installed 53c383ebc5dc 15 seconds ago 270.9 MB centos 6.6 8b44529354f3 2 weeks ago 202.6 MB
なお、イメージ化してもコンテナは残り続けるので、rm
コマンドで明示的にコンテナを削除する。
# docker rm `docker ps -aq`
イメージからhttpdを起動
上で作成したイメージcentos:httpd_installedから、httpdを走らせてみる。
2つの方法がある。1つは、docker run
でhttpdを指定する方法。
# docker run -d -p 8080:80 centos:httpd_installed /usr/sbin/httpd -DFOREGROUND
ここでのポイントは以下のとおり。
もう1つは、一度コンテナで/bin/bashを走らせ、httpdをバックグラウンドで起動後、Ctrl-P, Ctrl-Qでコンテナからデタッチする方法。
# docker run -p 8080:80 -ti centos:httpd_installed /bin/bash [root@9964dde4e945 /]# service httpd start [root@9964dde4e945 /]# # detach; Ctrl-P Ctrl-Q #
1コンテナ1プロセスが定石とされていることから、1つめのほうが望ましそうだ。参照: http://docs.docker.jp/engine/articles/dockerfile_best-practice.html
どちらの方法でも、ホストからwgetを打てばhttpdが動作していることを確認できる。
# wget http://localhost:8080/index.html
httpdを監視
コンテナの中のhttpdを監視するケースを考える。
1つめの方法の場合(docker run
でhttpdを直接立ち上げた場合)、docker exec
を使うことで、コンテナで一時的に/bin/bashを走らすことができる。
# docker exec -it `docker ps -q` /bin/bash [root@9beb6db80222 /]# /etc/init.d/httpd status # 状態確認 httpd (pid 1) is running... [root@9beb6db80222 /]# exit exit
また、2つめの方法の場合(docker run
で一度コンテナに入ったあとにバックグラウンドでhttpd起動)、docker attach <container-id>
を使うことで、デタッチしたコンテナに再びアタッチできる。
コンテナの停止
stop
/kill
コマンド。
# docker stop <container-id>
参考) stopとkillの違い: http://elendia.hatenablog.com/entry/2014/09/16/040659
再び起動するときはdocker start
コマンド。
# docker start 9beb
イメージの削除
イメージを削除したい場合は、docker rmi
コマンド。
# docker rmi <image id>
スクリプト化
Dockerfileにより、イメージ作成をスクリプト化できる。
以下の内容でDockerfileという名前のファイルを置く。
FROM centos:6.6 RUN yum -y install httpd RUN echo 'Hello world' > /var/www/html/index.html EXPOSE 80 ENTRYPOINT /usr/sbin/httpd -DFOREGROUND
Dockerfile作成後、build
コマンドでイメージを作成。
# docker build -t centos:httpd_installed .
-t
でイメージ名を指定する。末尾の.
は、「Dockerfileを含むディレクトリ」を指定している。
そしてrun
でコンテナを起動すると、DockerfileのENTRYPOINTで指定したコマンドが実行される。
# docker run -p 8080:80 -d centos:httpd_installed
AWSでCentOS 5をインポート
CentOS 5の大雑把なAWSインポート手順。以下のページを参考に、比較的簡単にできた。
参考) http://understeer.hatenablog.com/entry/2014/04/09/172554
実行環境はMac OS X. 手順としては、
- VirtualBoxでVMを作成
- VBoxManageコマンドでRAW形式に変換
- ec2-import-instanceでec2インスタンスとしてインポート
ec2-api-toolsとawscli, あとVirtualBoxをインストールしておく。
# brew install ec2-api-tools # brew install awscli
1. VirtualBoxでCentOS 5.Xのイメージ作成
CentOS 5のisoをどこかからダウンロードしてインストール。VMの形式はvdiを選択しておく(*)
(*) VMWareの形式であるvmdkを選択することもできる。実際、後のec2-import-instanceでvmdkがサポートされているので、vmdkで作ったほうがベターである。しかし、ec2-import-instanceの際に、なぜか暗号の方式が違うというエラーで失敗。なので、一旦vdiで作って次の手順でrawに変換している。なお、Virtual PCの形式であるvhdを選択することもできるが、試してない。
なお、rootパスワードでsshログイン出来るようにしておく。デフォルト設定では出来る。
2. vdiからrawに変換
# VBoxManage clonehd /path/to/CentOS5.11.vdi /path/to/CentOS5.11.raw --format RAW
3. VMイメージをインポート
あらかじめS3のバケットを作っておき、そこにVMイメージをアップロードする。
# ec2-import-instance /path/to/CentOS5.11.raw -t t2.micro \ -f RAW \ -a x86_64 \ -p Linux \ --region ap-northeast-1 \ --availability-zone ap-northeast-1a \ --bucket bucket_name \ --subnet subnet-aaaaaaaa \ -o S3_OWNER_ACCESS_KEY \ -w S3_OWNER_SECRET_KEY \ -O AWS_ACCESS_KEY \ -W AWS_SECRET_KEY
S3にアップロード後、ec2インスタンスが作成される。ec2インスタンスを立ち上げ、sshでrootログインできることを確認したら(*), 一旦stop.
(*) 運用時はもちろんもっとセキュアにすべき。。。
4. AMIを作成
マネージメント・コンソールなどからAMIを作成。これで基本的には完了。
5. S3に上げたVMイメージを削除
最後にS3に残ったVMイメージを削除。おしまい。
# aws s3 rm --recursive s3://bucket_name/raw_image_uuid
高遠 桜祭りの夜桜
長野 高遠の桜は、2015年は4/11, 12あたりがピークだったようだ。まさにその期間に夜桜を見に行った。
東京の上野公園などとは大違いで、酒臭くない。宴会は禁止のようだ。まさに天下の桜を愛でることができたのだ(^^