「はじめてUNIXで仕事をする人が読む本」を読んだ
はじめに
オープンソースカンファレンス2014に参加してきました(今更ですが).
オープンデータハッカソンに参加したり(楽しかったので次回も参加できたら是非), LT(カーネル空間上に草生やす発表が特に面白かったです)を楽しませてもらったり,Sinatra札幌ブースでは僕が作った未完成ゲーム(お化けをやっつけるゲーム)が走っておりヒヤヒヤしたりと(展示していただいて感謝)充実した一日でした.
オープンソースカンファレンスの懇親会にも参加させていただきました.ジンギスカン美味しかったです.懇親会ではLTが再び開かれていたり,様々なグッズが貰えるじゃんけん大会(オライリーTシャツ頂きました)や学生・駆け出しエンジニア向けにグッズのバラマキがありました.
グッズのバラマキでは,以前から読みたかった「はじめてUNIXで仕事をする人が読む本」というのを頂きました.何方から「読んだらブログに書いてね」と言われた気もしたので大分時間が経ってしまいましたが,感想を載せておきます.遅くなってすみません.
構成
以下が本書の構成です.てんこ盛りですね.しかし,これでざっと200ページ弱.なので,UNIXはどういうものか,何が便利なのかよくわからないという読者には最適な本だと思います. 事実,僕も普段からUNIX(OSXの上)を使っておりますが,周りに使える人も居ないまま独りで学んだこともあって,UNIX使いはこのくらい使えれば良いよという指標を頂いたようで安心できました. それだけでも読む価値はあったと思います.
第1部 生活環境編 第1章 ログインログアウト 1.1 そもそもログインとは 1.2 TELNETによるリモートログイン 1.3 SSHによるリモートログイン 1.4 ログアウト 第2章 UNIXの基本操作 2.1 シェル 2.2 リダイレクションとパイプ 2.3 UNIXのファイルシステム 2.4 基本のファイル操作 2.5 パーミッション・オーナーの管理 2.6 正規表現 2.7 grep 2.8 sed 2.9 awk 2.10 アーカイバ 2.11 その他のコマンド 第3章 テキストエディタ 3.1 基本のテキストエディタ 3.2 限定された環境でのファイル編集 3.3 ViとVim 3.4 Emacs 第4章 作業の自動化(シェルスクリプト) 4.1 シェルスクリプトによる作業自動化の必要性と利点 4.2 Bourne shellについて 4.3 簡単なスクリプトの作成と実行 4.4 シェルスクリプトの実用例 第5章 オンラインマニュアル 5.1 オンラインマニュアルを必要とする場面 5.2 氾濫する情報の危険性 5.3 manコマンド 5.4 infoコマンド 5.5 ヘルプメッセージ 第6章 セキュリティ 6.1 UNIXにおけるセキュリティ 6.2 ルート権限の獲得方法 6.3 共通鍵暗号と公開鍵暗号 6.4 SSHの応用 6.5 PGPによる暗号化、電子署名 第7章 UNIXシステム管理 7.1 UNIXにおける管理作業 7.2 起動とシャットダウン 7.3 ユーザとグループの管理 7.4 パッケージ管理 7.5 TCP/IPネットワーク管理 7.6 DNS(名前サービス) 7.7 サービスの管理 7.8 トラブルシュート 第2部 プログラミング環境編 第8章 UNIXプログラミング環境 8.1 プログラミング環境概要 8.2 C言語による開発実例 8.3 Javaによる開発実例 8.4 LL言語による開発実例 第9章 バージョン管理システム 9.1 バージョン管理システムとは 9.2 バージョン管理システムの種類 9.3 バージョン管理システムの使い方 9.4 Subversionの使い方 9.5 Gitの利用方法 第10章 ソースコードからのドキュメントの作成 10.1 はじめに 10.2 ドキュメント生成ツールの種類 10.3 ドキュメント生成ツールの利用方法 第11章 ソフトウェアライセンス 11.1 ライセンスを考慮する理由 11.2 オープンソースライセンス 第3部 ネットワーク技術編 第12章 UNIXとネットワーク技術 12.1 TCP/IP実装の公開と普及 12.2 LANとWAN 12.3 ネットワーク端末としてのUNIX 第13章 OSI参照モデル 13.1 OSI参照モデル 13.2 TCP/IPとOSI参照モデル 第14章 データリンク層 14.1 データリンクとは 14.2 データリンクの基本 14.3 Ethernet 14.4 無線LAN 14.5 Point-to-Point接続 第15章 IPと関連プロトコル 15.1 IPの基本 15.2 IPv4とIPv6 15.3 IPアドレス 15.4 特殊なIPアドレス 15.5 ルーティング 15.6 関連プロトコル 第16章 TCPとUDP 16.1 ポート番号 16.2 UDP 16.3 TCP 16.4 TCPのコネクション 16.5 TCPの通信 16.6 TCP通信の制御 16.7 TCPとUDPの使い分け 第17章 アプリケーションプロトコル 17.1 Webアクセス(HTTPHTTPS) 17.2 電子メール(SMTPPOPIMAP) 17.3 リモートログイン(TELNETSSH) 17.4 ファイル転送(FTPrsync) 17.5 ファイル共有(NFSSMB) 17.6 VoIP(SIPRTP) 17.7 システム運用管理(DNSDHCPNTPSNMP) 17.8 Xプロトコル 第18章 IP関連の技術 18.1 名前解決 18.2 IPアドレスの付与 18.3 アドレス変換(NAT・NAPT・IPマスカレード) 18.4 トラブルシューティング 第19章 ネットワークセキュリティ 19.1 ネットワーク上の攻撃 19.2 認証システム 19.3 通信フィルタとファイヤウォール 19.4 通信の暗号化 19.5 VPN
良かったところ
本当にざっくりと網羅的にUNIXの便利ツールの使い方と紹介が書かれており,さきほど書いた指標を知りたい人におすすめの一冊です.ただ,UNIXのみというよりも,オープンソース界隈で必要とされるツール(VCS,ソフトウェアライセンスとか)の紹介が多く,Linux使いも読んでも良さそうな記述が多かったです(ところどころLinuxの話も記載されている).
また,低レイヤな部分についても書かれており(OSI参照モデルなど)こういう大事なところもきっちりフォロウしているのは凄いと思いました.
とりわけ面白かったところ
悪かったところ
網羅的に書かれすぎており,一つ一つの話について消化不良感が否めないです. ソフトウェアライセンスについてもう少し細かい紹介が欲しかったです. なので,この一冊から普段使っているツールについて新しい知識を得るということは期待しないほうが良いです(そういう本ですし).
LL言語の紹介では本書の紹介ではpythonやrubyについて書いてあるにも関わらず,perlの基本的な紹介で終ったりと,ちょっとくらい対象読者に書かれていたPythonやRubyについても紹介したらどうかなとは思いました.
まとめ
日頃からUNIXに触れる人にとっては一般的にこのくらい知っておけばOKという基準が示されているようで安心できます.
UNIXを使ったことがない人にとっては,網羅的に書かれているので,読んだら一つ一つ後で調べたら良いかもしれません.
gunicorn+nginx+flaskで動かしてみた
はじめに
Flask製のアプリケーションをgunicornとnginxを使って動かす方法をメモしておきます.
動かすにあたって簡単なサンプルコードを載せておきます
ここではDebian7を対象に書きます.
アプリケーションの全体構成
ここではhelloというアプリケーションでアクセスされると「Hello!」と返してくれるウェブサプリケーションを想定します.
初期の全体のディレクトリ構成は以下のようになります
/site ├── hello.py └── tmp
FlaskでHello!を出す
hello.py
#!coding:utf-8 from flask import Flask app = Flask(__name__) @app.route('/hello', methods=['GET']) def hello(): return 'Hello!' if __name__ == '__main__': app.run()
これだけです.
flaskの細かい使い方は以前のブログ記事を参考にしてください フレームワーク素人がFlask触ってみた
nginxの設定
nginxでgunicornより生成されるsocketファイルを読むための設定を行ないます.
vim /etc/nginx/site-available/default
upsteram hello{ server unix:/site/tmp/unicorn_flask.sock } server { location /hello{ proxy_pass http://hello } }
gunicornの設定
先程nginxで指定したsocketファイルを次のように生成します.
/site上で
gunicorn hello:app --bind unix:./tmp/gunicorn_flask.sock -D
あとは
/etc/init.d/nginx reload
localhost/hello
にアクセスしてhello!が返ってくることを確認
まとめ
gunicornとnginx,flaskの連携についてまとめた.
ArduinoをCLIベースに開発できるino
はじめに
最近は電子工作にArduinoを使うことが多いです. 近年では電子工作の裾野を広げる意味では一躍買っているマイコンですね.
Arduinoの公式では書き込みやプログラミングが行えるIDEが配布されています.多くのユーザはそちらのIDEを使うことが多いかもしれません.しかし,VimやEmacsなど自分の好きなエディタやCLIを使いたい方も居ると思います. 僕も普段の開発にはVimを使うので,そのような場合は作成したコードをIDEに読み込ませてからArduinoへの書き込みを行なうという面倒なことをしてました.
今日はそんな面倒なことをしているかもしれない方へinoというCLIで扱えるArduino開発環境を紹介します.
inoを使えばプロジェクトのディレクトリ生成からビルド・書き込み,シリアル通信までできます.
inoのインストールと概要
inoはpythonで作られており,pypiにも登録されているのでpipを使ってインストールができます.
ただし,python3では動作しなかったので,python2.7で導入することを推奨します.
なおインストールは
pip install ino
からできます.
inoはプロジェクト生成からコードのビルド,マイコンへのプログラムアップロード,シリアル通信までサポートしています.
以下に普段の開発で最低限使うコマンドをまとめました.
コマンド
といったところでしょうか.他にもコマンドが沢山あります.
ino -h
から確認ができます.
実際に使ってみる
ざっくり説明したところで,具体的な使い方を示しましょう.
ここではArduinoからシリアル経由でHelloWorldをひたすら送りつづけるようなプログラムを作ることを目的に説明します.
まずはプロジェクトを生成しましょう. 空のディレクトリを生成する必要があります.
ここでは
プロジェクト名:HelloSerial(任意)
としましょう.なので
mkdir HelloSerial
でプロジェクトディレクトリを生成できます.
HelloSerialに移動して
cd HelloSerial
そしてプロジェクトの生成をします.
ino init
すると
. ├── lib └── src └── sketch.ino
というディレクトリが作成されます.
あとはsrcにあるsketch.inoにコードを書いていくだけです.
void setup() { Serial.begin(9600); } void loop() { Serial.println("HelloWorld"); }
書き込んで保存したら次はビルドです
ino build
で実行できます.
ビルドに成功したら
ino upload
でArduinoにアップロードします.
アップロードしたら今度はHelloWorldがシリアル通信で送られているか確認しましょう.
ino serial
でArduinoからHelloWorldが送られてくれば成功です.
まとめ
inoを使えば,コードのビルド,書き込み,アップロードなどArduinoで開発するときに必要なことが一通りできる.
シンプルなThreading
はじめに
昨日,Threadingを使用したコードを書きました. 書いた動機としては,もともとスレッド処理を書いたことがない僕は少してこづったことと,オブジェクト指向的なコードとかはググれば出るのですが簡単なのが少なかったからです.頭の中を整理するつもりでメモしておきます.
そもそもThreadって何?
まずスレッドの意味ですが,「プログラムの実行コード一つ辺りの単位」のことらしいです. つまり2スレッドは実行コードが2つ走っているということになります.
実行コードというのはプログラムが終了するまで実行しつづけようとします. ですので実行コードが終了するということはその実行コードのスレッドが一つ消えるということになります.
ではプログラム言語に搭載されている機能としてのスレッドとはどういう意味をなすのかですが,これは実行コードを複数扱ったり停止したり破壊したりと実行コードそのものを制御するためのものです.「実行コード中に停止させたい」,「いくつか実行コードがあってそれらを並列に動かしたい」という場面に有効です.
シンプルなThreadingコード
まずはfooという"foo"という文字列を吐きつづける実行コード(関数という形ですが)をthreadingから制御してみようと思います.
実行コードの生成と開始をして,1秒待ったあと停止させるというものです. つまり,1秒間メインコードが停止しているときでも関係なくfooは動いていることになります.ですので,1秒間fooを出力するはずです. なお,Pythonには停止にあたるものが無いので,ここではflagを使ってwhileループを抜けさせたりするのに使ってます.
import threading import time def foo(): while flag: print("foo") th=threading.Thread(target=foo) flag=True th.start() time.sleep(1) flag=False th.join()
注目すべきはflagをTrueにしたりFalseにするタイミングですね.flagはfoo関数のwhileを無限ループさせるのに必要となる変数です.flag=Trueであればwhile Trueとなりprint("foo")が無限に実行されます.Falseにすればwhile Falseとなりwhile文を抜けます.
実はこのwhileの制御が少し悩みました.whileを使って書きたくないなと思いつつも,今のところはflagによる制御が簡単かなと思っています.もし二回個別に実行したいときには再びthreading.Threadで生成してあげる必要がありますので注意してください. 次のようにするともう一度実行できます.
import threading import time def foo(): while flag: print("foo") th=threading.Thread(target=foo) flag=True th.start() time.sleep(1) flag=False th.join() th=threading.Thread(target=foo) flag=True th.start() time.sleep(1) flag=False th.join()
また,スレッドにはjoinというのがあります.これもよく使われるみたいです. これは実行コードが終了するまでメインコードの動きを止めることができます.
例えばfooとhogeの二つの関数があり,fooを終えたあとにhogeを開始したいとします. しかしスレッドではfooとhogeを次にように書くとほぼ同時に実行されてしまいます.
import threading def foo(): for i in range(10): print("foo:"+str(i)) def foo2(): for i in range(10): print("hoge:"+str(i)) th=threading.Thread(target=foo) th.start() th2=threading.Thread(target=foo2) th2.start()
結果
foo:0 foo:1 foo:2 foo:3 hoge:0 foo:4 hoge:1 foo:5 foo:6 hoge:2 foo:7 foo:8 hoge:3 foo:9 hoge:4 hoge:5 hoge:6 hoge:7 hoge:8 hoge:9
わかりやすくfooとhogeに対して数字を割りふりました. 同時に実行するとfooとhogeが混ざりあっているのがわかりますね.前半fooが多いのはstartのタイミングがfooのほうが早いからだと思われます.
ではfooをstart直後にjoinを置いてみましょう.
import threading def foo(): for i in range(10): print("foo:"+str(i)) def foo2(): for i in range(10): print("hoge:"+str(i)) th=threading.Thread(target=foo) th.start() th.join() th2=threading.Thread(target=foo2) th2.start()
結果
foo:0 foo:1 foo:2 foo:3 foo:4 foo:5 foo:6 foo:7 foo:8 foo:9 hoge:0 hoge:1 hoge:2 hoge:3 hoge:4 hoge:5 hoge:6 hoge:7 hoge:8 hoge:9
このようにfooが終わるまで待ってくれています.この例だとシングルタスクで動かしても大差ありませんが,例えばfoo,hoge,barの3つのスレッドがあり,fooとhogeはほぼ同時に走らせてbarはfooとhogeの後に実行したいときなんかは有効ですね.
まとめ
スレッドの基本的な考えかたと使いかたをメモしました.
スレッドとは実行コードの単位を示す.
PythonにはThreadingというスレッドそのものを扱うライブラリがあり,実行コードを並列に実行したり直列に実行したりできる.
MongoEngineつかってみた
はじめに
前回MongoDBをつかってみたという記事を載せました.その記事ではpyMongoを利用したMongoDBの操作を紹介しましたが,今日はPython上でMongoDBをOSMとして扱うことのできるMongoEngineの紹介をします.
MongoEngineインストール
インストールは簡単
pip install mongoengine
のみです.
使い方
学生情報を扱うデータベースを例に話を進めていきます. まずは,ドキュメントの追加と参照について説明します
追加と参照
データベース名:studentinfo
クラス名: Student(学生情報を扱う)
要素:Name(学生名)
要素:Number(学生番号)
import mongoengine mongoengine.connect("studentinfo") class Student(mongoengine.Document): Name = mongoengine.StringField() Number = mongoengine.IntField() #DBの初期化を行なう(ブログの内容には直接関係しない) Student.drop_collection() db=Student() db.Name="Taro" db.Number=1 db.save() for data in Student.objects: print data.Name print data.Number
出力だけならこれだけです.
もし特定のデータ(Number1にしましょう)だけ取りだしたいなら
import mongoengine mongoengine.connect("studentinfo") class Student(mongoengine.Document): Name = mongoengine.StringField() Number = mongoengine.IntField() #DBの初期化を行なう(ブログの内容には直接関係しない) Student.drop_collection() db=Student() db.Name="Taro" db.Number=1 db.save() for data in Student.objects(Number=1): print data.Name print data.Number
のようにすればNumber1のデータだけが表示されます
親子関係にあるデータベース
では次はMongoEngineで親子関係にあるデータベースを組んでみましょう. 例題として先程のStudentの加えて試験の結果を子とします.
データベース名:studentinfo
クラス名:Student
要素:Name(学生名)
要素:Number(学生番号)
クラス名:Math
- 要素:score(点数)
クラス名:Science
- 要素:score(点数)
クラス名:English
- 要素:score(点数)
とします.
この場合はStudentから各科目(Math,Science,English)を呼べるようにします.
import mongoengine mongoengine.connect("studentinfo") class Math(mongoengine.Document): score = mongoengine.IntField() class English(mongoengine.Document): score = mongoengine.IntField() class Student(mongoengine.Document): name = mongoengine.StringField() math = mongoengine.ReferenceField("Math") english = mongoengine.ReferenceField("English")
こうします.実際にStudentを経由してMathやEnglishのデータを書き込むには 次のようにします.ここでは[学生名taro,数学100点,英語50点]というデータと[学生名jiro,数学70点,英語80点]として書いていきます
taro = Student() math = Math() english = English() math.score=100 math.save() english.score=50 english.save() taro.name="taro" taro.math=math taro.english=english taro.save() jiro = Student() math = Math() english = English() math.score=70 math.save() english.score=80 english.save() jiro.name="jiro" jiro.math=math jiro.english=english jiro.save()
とします.mathとenglishそれぞれのインスタンスに各点数を代入したのちstudentのクラス変数に渡してますね.
値を取り出すには
for student in Student.objects: print student.name print student.math.score print student.english.score
のようにします. おそらく
taro 100 50 jiro 70 80
と出力されるはずです.
もし複数件入力されており,名前が"taro"だけのデータが欲しいときには
for student in Student.objects(name="taro"): print student.name print student.math.score print student.english.score
結果
taro 100 50
のようにobjectsにname="taro"のように指定するだけです.
ここの部分を一つのコードにまとめると
import mongoengine mongoengine.connect("studentinfo") #クラスの定義 class Math(mongoengine.Document): score = mongoengine.IntField() class English(mongoengine.Document): score = mongoengine.IntField() class Student(mongoengine.Document): name = mongoengine.StringField() math = mongoengine.ReferenceField("Math") english = mongoengine.ReferenceField("English") #DBの初期化を行なう(ブログの内容には直接関係しない) Student.drop_collection() #taroとjiroのドキュメントを追加 taro = Student() math = Math() english = English() math.score=100 math.save() english.score=50 english.save() taro.name="taro" taro.math=math taro.english=english taro.save() jiro = Student() math = Math() english = English() math.score=70 math.save() english.score=80 english.save() jiro.name="jiro" jiro.math=math jiro.english=english jiro.save() #Studentクラスに書かれているドキュメントをすべて取得 for student in Student.objects: print student.name print student.math.score print student.english.score #taroのドキュメントのみ取得 for student in Student.objects(name="taro"): print student.name print student.math.score print student.english.score
上書き
次に既存のデータを上書きしたときについてですが,上記のjiroをsaburoに変更してみましょう.
jiro = Student.objects(name="jiro") jiro.update(set__name="saburo")
のようにobjectsでデータを抜きだしてからupdate文で更新します.
更新の際にはset__のようにqueryを指定することができます.set__
query以外にもpush__
, unset__
, pull__
などがあります
詳しくはこちらをお読みください(http://mongoengine-odm.readthedocs.org/guide/querying.html) .
まとめ
MongoEngineでデータの追加や参照,更新についてまとめました.
MongoDBつかってみた
はじめに
Flaskやsinatraを使ってウェブアプリケーションを作成する際に,どのDBを採用するかというのは仕様決定上重要になります.
僕はこれまでDBというとMySQLやSQLiteのようなRDBMSを使っていたのですが,sinatra札幌さんのほうでflask上でNoSQLであるMongoDBを使用する機会を頂き,ここにMongoDBの概要と使い方,Pythonからどう制御するのかについて簡単にまとめました.
MongoDBとは
RDBMSを使用していた方にとってはMongoDBはちょっと異質に見えるかもしれません. RDBMSではデータ構造を明確化し,数学的な堅牢性を持っているイメージですね.SQLとよばれる言語を使用することでデータのソーティングなどを行ないます.
MongoDBではデータ構造はRDBほど明確化しなくても使用することができ,SQLのような言語を使う必要がありません.ドキュメント指向データベースと呼ばれており,データのやりとりはドキュメントとよばれる構造データにJSON形式で記述して使います.そのためプログラミング言語からSELECT * FROM テーブル名のようにコード中にSQLを書くこと必要がなく,使用言語がJSONフォーマットを扱えさえすれば配列やリストのような形でDBを操作できます.
MongoDBの用語
RDBMSを使用しているとデータベースの選択やレコードの選択などを考えてしまいますが,MongoDBは独特のドキュメント指向データベースと呼ばれている通りRDBMSとは異なる概念を持っています. ここではその概念と用語についてまとめてみました.
データベース:一つのアプリケーションで使用するコレクションを格納しておくもの.コレクションは複数持つことができる.
コレクション:ドキュメントを格納しておくもの.複数のドキュメントを持つことができる.
ドキュメント:商品ID,品名,価格などのデータそのものを格納できる.商品ID,品名のみなど可変長に扱える.入力形式はハッシュのようにKeyとValueの関係で保持される.
つまり包含関係で言えば「ドキュメント⊆コレクション⊆データベース」となります.
とりあえず動かしてみる
MongoDBを起動した状態で「mongodb」とシェル上からタイプするとMongoDBにアクセスできます.ここでは次のようなものを満すデータベースを作ってみましょう.
- データベース名:examDBという学校の試験を
*コレクション:Math, Englishの2教科を現わすコレクション
*ドキュメント:Name,Gradeの2項目.ただしGradeはテストを受けていない場合はつけない場合がある.
*要素:NameはTaro,Jiro, Saburoの3人.Taroは「Math40点,Englishは受けていない」. JIroは「Math100点,Englishは80点」.Saburoは「Mathは90点Englishは70点」.
データベースの生成や選択は
use examDB
としEnterを叩くだけです.簡単ですね 次にコレクション名とドキュメントを生成します.コレクションはMathとEnglishの2項目,ドキュメントはNameとGradeの2項目ですね.MongoDBではそれらを直接指定できます. まずはMathにそれぞれ項目を入力していきましょう.
db.Math.insert({Name : "Taro", Grade: "40"}) db.Math.insert({Name : "Jiro", Grade: "100"}) db.Math.insert({Name : "Saburo", Grade: "90"})
です. dbは上記のuseコマンドでexamDBをすでに選択しています.db.Mathとすることでコレクション名Mathを生成し操作できます.次にドキュメントを挿入したいのでdb.Math.insertのように指定できます.insertについては中身はJSONフォーマットで入力するだけなのでdb.Math.insert({ドキュメント項目名(Key) : ドキュメント項目値(Value), ・・・})です. 上記では3項目あるので3行分記述してます.
次にEnglishについても同様に打ちましょう.
db.English.insert({Name : "Taro"}) db.English.insert({Name : "Jiro", Grade: "80"}) db.English.insert({Name : "Saburo", Grade:"70"})
ですね.Taroは受けていないのでGradeの項目は入力してません.
では次は挿入されたデータを呼び出してみましょう. たとえば,Mathを呼び出したいときには MongoDBでは
db.Math.find()
だけです.これで入力した3項目が返ってきます.
MathのうちTaroのデータだけ呼びたいときには
db.Math.find(Name:"Taro")
だけです.
ここでは触れてませんが,コレクションの中にも子コレクションを生成することもできます. その場合もコレクション名が増えるだけで操作は,findやinsertを使用することができます.
PythonからMongoDBを操作する
PythonからMongoDBを操作してみましょう. PythonからMongoDBを扱えるライブラリにpymongoというのがあります. 「pip install pymongo」とタイプすることでインストールができると思います.
では先程の操作をpymongoからやってみましょう
from pymongo import MongoClient client = MongoClient()#接続先を指定Localhostの場合はvoidで良い db = client['examDB']#データベースを選択 #Mathの項目追加 db.Math.insert({'Name' : 'Taro', 'Grade':'40'}) db.Math.insert({'Name' : 'Jiro', 'Grade': '100'}) db.Math.insert({'Name' : 'Saburo', 'Grade': '90'}) #Englishの項目追加 db.English.insert({'Name' : 'Taro'}) db.English.insert({'Name' : 'Jiro', 'Grade': '80'}) db.English.insert({'Name' : 'Saburo', 'Grade':'70'}) #Mathのfind for data in db.Math.find(): print(data) #MathのTaroだけ呼びだす for data in db.Math.find({'Name':'Taro'}): print(data)
これらの形であればリストに格納したりイテレータのような形で扱うことができますね.
まとめ
MongoDBはRDBMSとは違ったSQLを使用しないデータベースであり,Jsonフォーマットでデータを扱えます.
概念用語としてデータベース,コレクション,ドキュメントがあります. ここでは学校のテストデータを例にmongoDBとPython上で試してみました.
kivyでデスクトップアプリケーション
はじめに
クロスプラットフォームでGUIアプリを開発するためのフレームワークにkivyがあります kivyのホームページ.
ここ最近,デスクトップアプリケーション開発といえば個人的にkivyを使用することが多くなりました.pythonにはpyQTやwxpython,Tkinterなど多くありますが,pyQTはウェブや書籍を参考にできるほど文献が少ないこと,wxpythonの場合は更新がすでに止まっており,採用には至りませんでした.Tkinterを使うことも考えられますが,kivyのほうがスマートフォン上で動作するという違いがあり興味が湧いたのでkivyを使うに至りました.
ここではkivyの基本構成について忘れないようにメモしておきます.
必要なリファレンスについては
と
PythonでかんたんiOSアプリプログラミング―Kivyによるマルチタッチアプリケーション制作
を参考にしました.
kivyのインストール
少し前のブログをお読みください kivyをpipからインストールしてみた
本記事ではPythonは2.7.6,kivyのバージョンは1.8を対象に書いております.
kivyの開発
まずはHelloWorld
kivyには様々なウィジェットがあります.そのなかにもラベルと呼ばれるアプリケーション上に文字列を表現するものがあります.ここではラベル上に「HelloWorld」を出力するコードを示します.
from kivy.app import App from kivy.uix.label import Label class TestApp(App): def build(self): return Label(text='Hello World') TestApp().run()
これだけですね.
from kivy.app import Appについてはアプリのインポート,二行目はラベルのインポートです.
公式サイトのhomepageにも載っていますが,labelとLabelの箇所をそれぞれbutton,Buttonに変更すればボタン上にHelloWorldが表示されます.
pythonでファイルを指定すれば実行できます.
ちょっとまともなGUIアプリ
さて,HelloWorldの例を読むだけではreturnでボタンを返すだけでは面白くないかもしれません. ここでは僕が普段利用しているファイル関係を示しておこうと思います.
以下に基本的なファイル関係を示しておきます.
├── main.py ├── my.kv
main.pyという実行ファイル,my.kvというGUIレイアウトなどを記述するファイルです. メインとなる実行ファイルについてはHelloWorldを表示したようにPythonで処理を記述するものです.
my.kvはkivyにおけるデザイナの位置やIDと呼ばれるGUI部品とコードを紐付けるものを定義するものです.pythonコードで部品を設置しなくてもmy.kvに部品を配置することで,main.pyでは見た目を気にせず処理内容にだけ注力することができます.
また,名前を変更することも可能ですが,初期設定ではmy.kvという名前のファイルを読むように設定されており,そこについてはここでは触れません.
以下に,ボタンを押したらラベルの値に現在時刻を表示するアプリを例にmain.pyとmy.kvの設定や関係を説明していきます..
まずはmy.kvの説明をします.
今回作るアプリはボタンを押したらLabel上に現在時刻を表示するものです. そのため,ウィジェット名とラベル,ボタンをそれぞれ一個づつ配置する必要がありますので配置していきましょう.
まずは,ウィジェット名と任意の名前をラベル・ボタンそれぞれに付けていきましょう.
ここでは
ウィジェット名はtimerWidget
ラベルの名前はlabeldatetime
ボタンの名前はbuttoncount
としました.
それぞれの部品設定を設定を以下に示します.
labeldatetimeの設定
フォントサイズ:50pt
位置(横,縦):(中央,アプリ上部)
初期設定の文字列:「time」
buttoncountの設定
*ID: buttoncountval
*フォントサイズ:50pt
*位置(横,縦):(中央,アプリ上部から下方向に向かって180ピクセル)
*ボタンサイズ(幅,高さ):(140,70)
*設定の文字列:「Click!」
これをkvファイルで表現すると次のようになります.
my.kv
#:kivy 1.8.0 <timerWidget>: labeldatetime: labeldatetimeval buttoncount: buttoncountval #Labeldatetime Label: id: labeldatetimeval font_size: 50 center_x: (root.width/2) top: root.top text: 'time' #buttoncount Button: id: buttoncountval font_size: 50 center_x: (root.width/2) size: 140,70 top: root.top-180 text: 'Click!'
まず一番上で,kivyのバージョンとウィジェット名,部品IDとpythonコードで使用する部品名を紐付けています. あとはそれぞれフォントサイズや位置,部品サイズ,部品の文字列などを定義しているだけです.
次にmain.pyで処理を書いていきましょう.
ここではウィジェットとして定義した部品を操作する箇所です.ボタンが押されたらその都度表示時刻を現在時刻に置きかえるというものです.
main.py
# -*- coding: utf-8 -*- import kivy kivy.require('1.8.0') from kivy.app import App from kivy.uix.widget import Widget from kivy.properties import ObjectProperty import datetime class timerWidget(Widget): labeldatetime = ObjectProperty(None) buttoncount = ObjectProperty(None) class MyApp(App): def buttoncount_clicked(self, src): self.root.labeldatetime.text = str(datetime.datetime.now()) def build(self): self.root = timerWidget() self.root.buttoncount.bind(on_press=self.buttoncount_clicked) return self.root if __name__ == '__main__': MyApp().run()
上から説明するとまずは,kivyのバージョン,アプリ起動に必要なAppとWidget,kvファイルで定義したWidgetを取りだすObjectProperty,現在時刻を扱うdatetimeをインポートしています.
class timerWidget(Widget)ではmy.kvで紐付けられている部品を取りだしたり描画する箇所です. my.kvで定義した変数を左辺に置いて右辺にはObjectProperty(None)と記述するだけです.
class MyApp(App)では起動に必要な準備やイベントハンドラと呼ばれるボタンをクリックしたときの処理などを書いていきます.
timerWidgetを生成. つぎにボタンをクリックしたときの処理をbind(on_press= )で定義しています. 最後にウィジェット自体を返すだけです.
次にMyApp().run()で実行です
以下に実行画面を示します
実行画面(クリック時)
まとめ
簡単なkivyの使い方をまとめてみました. 必要な部品などの配置はkvファイルが担当し,部品を操作するのはmain.pyです.
kivyにはもちろんこれ以外にもたくさんの部品があります.
また形には見えない部品もあります.例を挙げれば一定の時間で自動で実行するClockなどです.機会があればその辺についても書きたいと思います.