2012-02-17
2012-01-06
Tinkererを使ってbitbucketでblogはじめました
TinkererはSphinxを利用して作られたblogツールです。Sphinxを使っていますのでreStructuredText形式で書くことができます。また、blockdiagをはじめとするSphinxの豊富な拡張機能を使うことができます。
今回はtinkererで作成したblogをbitbucketでホスティングしてみます。
bitbucketでのホスティング
bitbucketでは <username>.bitbucket.org という名前のレポジトリを作成し、そこにindex.htmlファイルを置くことでwebページのホスティングができます。これは普通のレポジトリですので、push/pullできますし、履歴管理も出来ます。
そして、実はこのレポジトリはprivateでも構わないのです。privateにすることで、draftなどを隠すことができます。あ、githubと違ってbitbucketはprivateレポジトリが作りたい放題です。
tinkererを実行
さて、実際にblogを書いてみましょう。
その前に、bitbucketで以下のレポジトリを作成します
- <username>.bitbucket.org (private レポジトリ)
あとはtinkererを実行します
% mkdir blog % cd blog % tinker -s ## ファイルができる % vi conf.py (タイトルなどを設定する) % tinker -p "first post" (投稿する) % vi 2012/01/04/first_post.rst (適当に書く) % tinker -b ## build
これでblog/html以下にhtmlファイルが生成されます。
次に普通にレポジトリを作成しましょう。
% hg init
% vi .hg/hgrc
[paths]
default=ssh://hg@bitbucket.org/<username>/<username>.bitbucket.org
% hg add .
% hg commit -m "first post"
% hg push
これで <username>.bitbucket.org でtinkererによるblogが出来ました。 http://<username>.bitbucket.org にアクセスしてみてください。
あとは
- % tinker -p "なにか"
でページを作成・編集してから
- % tinker -b
でhtmlを生成し、add、commit、pushをすれば更新できます。また、
- % tinker -d "draft"
でdraftsディレクトリ以下に下書きを作成することも出来ます。
注意点
bitbucketによるホスティングではindexは禁止されているのでdrafts以下は見えません。privateレポジトリなのでレポジトリに他の人がアクセスすることもできません。しかし、直接URLを指定することでファイルの取得ができてしまいます。
そのため、例えばconf.pyなどはほぼ公開と同じようになってしまいます。また、drafts以下のファイルもファイル名が分かってしまうと取得できてしまいます。
実例とbitbucketの注意点
というわけで、英語ブログをはじめました。
ぼくの普段使っているbitbucketのアカウントはr_rudiなのですが、ホスティングする際にこのアンダースコアが問題になってしまいました。URL的にだめみたいです。twitterに投稿しようとしてできなくて悩みました。アンダースコアはRFC 2396ではOKなような気がするのですが、あんまり詳しく調べていません。
追記
blog/html/index.html へのリダイレクトですが、tinker -s で初期設定をtinkererが吐き出した時に一緒にトップディレクトリにblog/html/index.html へのリダイレクトを行うindex.htmlが吐き出されます。
追記その2
conf.pyとかはダウンロードできちゃうよ、って書きましたけど、よく考えればブランチを切ればいいんでした。
- default
- 公開用ブランチ。index.htmlとblog以下だけ含まれている
- drafts
- 書き用ブランチ。その他のが全部含まれている。
としておいて、普段はdraftsブランチで書いておいて、公開する時にmergeすればいいんですね。
2012-01-04
Army of Darkness Defense
正月は「いまさらかよ」と言われそうですが、iPhoneアプリのArmy of Darkness Defenseをやってました。いや、かなりおもしろいわこれ。
初回プレイは
- Boomstick + Catapult
- Armored Guard + Arthur
でwave 50をクリア。Boomstickは範囲攻撃+再使用までの時間が短いので結構使えます。
次は
- Magic Words + Deathcoaster
- Horseman + Arthur + Archer
でクリアした後、EndlessモードでHorsemanをLv Maxまで上げて20体ぐらい出すと終わらなくなるというのを確認しました。
最後に
- Boomstick + Deathcoaster
- Peasant + swordboy
でLv50までクリアしました。
実はPeasantはやればできる子で、Lv Max(こいつだけLv11まで上がる)に上げてひたすら生産するだけでLv49までは勝てたりします。最初にちょっとironを貯めておいてwisemanも出しておくとよりいいかもしれません。ただ、Lv50はラスボスの攻撃力が高いのでArthurを出す必要と、Deathcoasterでがつんと削る必要とがありました。
最終的に全52個のarchivementsを全て集めました。いえい。
なぜか最終面だけ異様に難しいとかよくあるんですが、これはそういうこともなく、いろいろな遊び方ができるので非常に楽しめました。オススメ。
2011-12-15
multicornを使ってPythonでfdwを実装する
今の会社に入ってからPostgreSQLを使い始めました。というわけで、初心者ですがPostgreSQL アドベントカレンダー 2011に参加してみます。
さて、PostgreSQL 9.1からSQL/MED規格の一部である 外部データラッパ (FDW:Foreign Data Wrapper) がサポートされました。すでに PostgreSQL アドベントカレンダー 12月3日分にて、板垣さんが WebAPIをfdwから叩いてます。この記事では www_fdw という既存のfdwを利用する方法でしたが、今回は実際に自分でfdwを作ってみます。
fdwはAPIを6個程度書くだけで良いのでそれだけでもかなり書きやすいのですが、いかんせんCで書く必要があります。そこで、 multicorn を使ってpythonでfdwを書いてみました。
なにを題材に書こうかなと思ったのですが、Pure Pythonで作られた全文検索エンジンの Whoosh を使ってみました。
準備
まず、以下の二つをインストールする必要があります。
- whoosh
- multicorn
下にubuntuで叩いたコマンドを書いておきます。
% sudo atp-get install postgresql-9.1 # postgresql-9.1を入れる % sudo apt-get install python-dev # multicornのcompileにヘッダが必要 % sudo apt-get install python-pip # pythonのパッケージ管理ツールpipを入れる % sudo pip install pgxnclient # pgxnを扱うためのクライアント % sudo pip install whoosh # 全文検索エンジン % sudo pip install -e "hg+http://bitbucket.org/r_rudi/whooshfdw#egg=whooshfdw" # 今回実装したパッケージをbitbucketからインストールする % sudo pgxn install multicorn --testing # multicornを入れる
なお、今回はPostgreSQLサーバがpythonを叩くため、パッケージはvirtualenv環境ではなく、システム自体にインストールしてください。
whoosh index作成
全文検索するためにはまずインデックスを作成する必要があります。
registerというクラスを用意しておきましたのでそれを使います。
今回は、wikipediaの全ページのタイトルだけが含まれたファイルを検索してみます。
http://dumps.wikimedia.org/jawiki/20111203/ から jawiki-20111203-all-titles-in-ns0.gz をダウンロードし、/tmpに展開しておいてください。
from whooshfdw import register register.register(file='/tmp/jawiki-20111203-all-titles-in-ns0', indexdir='/tmp/indexdir')
手元のマシンではだいたい40分ほどかかりました。お試しの場合はhead -n 1000とかしてください。
なお、インデックスですが決め打ちで2-gramで作成してあります。このあたりはコードを読んでくださいね。
SQL
準備が整ったところでいよいよfdwです。まずは Server と Tableを作成します。
CREATE EXTENSION multicorn; -- multicornをDBにいれる CREATE SERVER whoosh_srv FOREIGN DATA WRAPPER multicorn options ( wrapper 'whooshfdw.whooshfdw.WhooshFDW' -- Server作成 ); CREATE FOREIGN TABLE whooshtable( -- FOREIGN TABLE作成 id numeric, title character varying ) server whoosh_srv options ( indexdir '/tmp/indexdir' -- インデックスの場所をオプションで指定 );
できたところで SELECT 実行です。
% psql -c "SELECT * from whooshtable where title LIKE '%どこでも%';" id | title ----+-------------------- 1 | どこでもまど 2 | どこでもドア 3 | どこでもパス 4 | どこでも大砲 5 | どこでもCHU 6 | どこでもドアー 7 | どこでもいっしょ 8 | どこでもチョコボ 9 | どこでもWiiの間 10 | どこでもドラえもん (10 rows)
ちゃんと返ってきてますね。
実装の解説
multicornを使ったfdwの実装は ForeignDataWrapper クラスを継承したクラスを作成し、コンストラクタである __init__ と実行メソッドである execute を実装するだけです。
__init__ではsuperを呼び出すだけです。また、実際の検索を行うexecuteの中では yield を使って値を次々に返して行くだけです。
下はfdwの機能に絞ったコードの抜粋です。(全部はbitbucketを見てください)
class WhooshFDW(ForeignDataWrapper): def __init__(self, options, columns): super(WhooshFDW, self).__init__(options, columns) self.columns = columns self.indexdir = options["indexdir"] # CREATE TABLE で指定したオプションを持ってくる def execute(self, quals, columns): for query in quals: # qualsはWHERE句の中身が入っている q = parser.parse(query.value) with ix.searcher() as searcher: count = 1 for r in searcher.search(q): res = {'id': count, 'title': r["title"].encode('utf-8')} yield res # 値を辞書形式で返してあげる count += 1
まとめると、
- __ini__の中でsuperを呼ぶ
- executeの中でyieldを使って値を次々に返せるようにする
これだけ。
注意点
なお、qualsというのはWHERE句の中身です。そしてwhere句は*必ず*適用されます。例えば、
def execute(self, quals, columns): for i in range(1,20): yield(i, "hoge")
としておいて、
SELECT * FROM whooshtable WHERE id = 10;
というSQLを実行した場合、「executeでqualはなにも使ってないんだから1から20まで表示されるだろう」と思いますよね。でもそうではなく、ここでは 10,hoge しか出てきません。
速度は?
実用を求めるならCで書けよな、と思いますが一応。
| 本体 | Mac Mini (mid 2011) |
|---|---|
| OS | Ubuntu on Virtualbox |
| CPU | 2.4GHz(Core 2 Duo) |
| メモリ | 8G |
| postgres | 9.1 |
PostgreSQLの設定はubuntuのそのまんまです。っていうか、VirtualBoxという時点で評価の意味がないような気がしますが…。
1247130行のwikipediaのタイトルだけを抜き出したものでindexを作成するのに
% time python register.py 2571.88s user 289.96s system 91% cpu 51:54.10 total
2571秒はだいたい42分。これをfdw経由で検索すると、
Foreign Scan on whooshtable (cost=10.00..15.00 rows=9999999 width=64) (actual time=619.132..620.073 rows=10 loops=1) Filter: ((title)::text ~~ '%どこでも%'::text) Foreign multicorn: multicorn Foreign multicorn cost: 10 Total runtime: 681.000 ms
でした。ちなみに普通にpythonで検索してみました。timeitを使って、100回実行して平均を出してみると、
% python search.py 15.917749 msec
おやまあ、やっぱりPostgreSQLからpythonを呼び出すコストが結構かかるようですね。pypyでも試してみたくなりますが止めておきます。
まとめ
今回は PostgreSQL 9.1から搭載されたfdwをPythonで実装できるmulticornを使って、pure pythonの全文検索エンジンwhooshをSQLから叩けるようにしてみました。
…字で書くとなんかむちゃくちゃですね。でも、やったことは非常に少しなのでPostgreSQLの拡張性すごい!ということで。
明日は DaiMotoh さん、お願いします。
2011-12-04
pysetup3のご紹介
python2ではsetuptoolsやdistutilsがありますが、python3では ”packaging”という新しいパッケージ用ライブラリが搭載されます。
pysetup3はこのpackagingを使うためのコマンドです。これは、setuptoolsやdistutilsを使うためのコマンドがpipやeasy_installである、という関係と同じです。
まとめるとこういう関係になります。(正確にはちょっとずれていますがまあこんなものかと)
| ライブラリ | ツール | |
|---|---|---|
| python3.2まで | distutils/setuptools/distribute | easy_install/pip/buildout |
| python3.3〜 | packaging | pysetup3 |
なお、packagingはpython2.4〜3.2ではdistutils2という名前でバックポートされ、サードパーティパッケージとして配布されます。
pysetup3のドキュメントはこちらです。
http://docs.python.org/dev/install/pysetup.html
使い方
pysetup3はpython3.3から標準搭載されます。python 3.3はまだリリースされていないので、使うには http://hg.python.org/cpython/ から開発版を取得してくる必要があります。あるいは、python2〜3.2で使うにはhttps://bitbucket.org/tarek/distutils2/wiki/Home からソースをとってくる必要があります。なお、distutils2の場合、listコマンドが使えないなどの制限がありますのでご注意ください。
さて、pysetup3の使い方です。まずはhelpを見ます。
% pysetup3 --help
Usage: pysetup [options] action [action_options]
Actions:
run: Run one or several commands
metadata: Display the metadata of a project
install: Install a project
remove: Remove a project
search: Search for a project in the indexes
list: List installed projects
graph: Display a graph
create: Create a project
generate-setup: Generate a backward-compatible setup.py
ちなみに、distutils2ではこうなります。
Actions:
run: Run one or several commands
metadata: Display the metadata of a project
install: Install a project
remove: Remove a project
search: Search for a project
graph: Display a graph
create: Create a Project
listがないのはどういうことだって言う感じですが…
検索 (search)
ということで、まずはbuchoパッケージを検索してみます。
% pysetup3 search bucho not implemented %
...
えーっと。実装されてないって…
気を取り直して次行きましょう。
インストール (install)
落としてきたtar.gzを使って install してみます。
% pysetup3 install bucho-0.1.1.tar.gz
Installing from archive: '/home/prosou/shirou/bucho-0.1.1.tar.gz'
Traceback (most recent call last):
File "setup.py", line 2, in <module>
import setuptools
ImportError: No module named 'setuptools'
failed to install
あー、buchoはsetuptoolsに依存しているのですね。pysetup3 install distribute をしたらこのエラーは出なくなりましたが、代わりに
option --single-version-externally-managed not recognized
と言われてしまいました。よく分かりません…
pysetup3の作者、tarekのパッケージなら平気だと思います。
% pysetup3.3 install flake8-1.0.tar.gz
.....
% pysetup3.3 list
'flake8' 1.0 (from '/home/rudi/local/lib/python3.3/site-packages/flake8-1.0-py3.3.dist-info')
Found 1 projects installed.
うまくインストールできたようです。
なお、インストールは
- pypi
- 検索はできなくてもインストールはできます。 pysetup3 install flake8としてください
- tar.gzへのURL (http://host/packages/project-1.0.tar.gz)
- setup.pyかsetup.cfgが含まれたディレクトリ
からもインストールできます。また、
% pysetup3 install project==1.0
というようにすることで、インストールするバージョンを決めることもできます。
インストール済みのパッケージリスト (list)
listで今インストールされているパッケージのリストが出ます。
% pysetup3.3 list 'flake8' 1.0 (from '/home/rudi/local/lib/python3.3/site-packages/flake8-1.0-py3.3.dist-info') Found 1 projects installed.
情報の表示 (metadata)
パッケージの情報を得るにはmetadataを使います。
% pysetup3.3 metadata flake8
Metadata-Version:
1.1
Name:
flake8
Version:
1.0
Platform:
UNKNOWN
Supported-Platform:
Summary:
code checking using pep8 and pyflakes
Description:
======
(以下省略)
また、-fをつけることにより、表示される情報を制限することも出来ます。
% pysetup3 metadata -f name -f version flake8
Name:
flake8
Version:
1.0
インストールされているものにしか使えないようです。
グラフの表示 (graph)
% pysetup3.3 graph flake8 'flake8' 1.0
依存するパッケージのグラフを表示してくれるそうです。
アンインストール (remove)
% pysetup3.3 remove flake8 'flake8' cannot be removed. Error: [Errno 18] Cross-device link
what? …ちょっと今回は追いませんが、これがきちんと出来るのがいいところなのに…
プロジェクトを作成する (create)
createコマンドを打つと、setup.cfgを対話型で作ってくれます。途中でyを答えると今のディレクトリをチェックして全部含めてくれますので便利です。
ちなみに、pysetupはsetup.pyではなく、setup.cfgを使うようになることに注意してください。 (このあたりはpycon 2011 JPのtarekの講演を参考にしてください。)
% pysetup3.3 create
Project name [setup]: test
Current version number [1.0.0]:
Project description summary:
> Thi is test
Author name: shirou
Author email address: rudy@example.com
Project home page: test
Do you want me to automatically build the file list with everything I
can find in the current directory? If you say no, you will have to
define them manually. (y/n): y
Do you want to set Trove classifiers? (y/n): y
Please select the project status:
0 - Planning
1 - Pre-Alpha
2 - Alpha
3 - Beta
4 - Production/Stable
5 - Mature
6 - Inactive
Status: 1
What license do you use?: BSD
Matching licenses:
1) License :: OSI Approved :: BSD License
Type the number of the license you wish to use or ? to try again:: 1
What license do you use?:
Do you want to set other trove identifiers? (y/n) [n]: n
Wrote "setup.cfg".
また、setup.pyがあると
% pysetup3 create A legacy setup.py has been found. Would you like to convert it to a setup.cfg? (y/n) [y]: y
と聞いてくれます。でもsphinxを試したら ImportError: No module named 'sphinx' と言われてしまいました。
互換性のためにsetup.pyを作る (genearte-setup)
% generate-setup The setup.py was generated
とすると、setup.pyが出来上がります。でも、現段階では別にディレクトリの内容を読んでくれるわけではなく、単にsetup.pyのひな形ができるだけです。
コマンド (run)
pysetup3には今まで述べてきたコマンドの他にも setup.py 相当コマンドがあります。 setup.pyが使われなくなる代わりに、今までsetup.pyで行ってきたことがここに入っているという感じですね。
% pysetup3 run --list-commands
List of available commands:
bdist: create a built (binary) distribution
bdist_dumb: create a "dumb" built distribution
bdist_wininst: create an executable installer for Windows
build: build everything needed to install
build_clib: build C/C++ libraries used by extension modules
build_ext: build C/C++ extension modules (compile/link to build
directory)
build_py: build pure Python modules (copy to build directory)
build_scripts: build scripts (copy and fix up shebang line)
check: check PEP compliance of metadata
clean: clean up temporary files from 'build' command
install_data: install platform-independent data files
install_dist: install everything from build directory
install_distinfo: create a .dist-info directory for the distribution
install_headers: install C/C++ header files
install_lib: install all modules (extensions and pure Python)
install_scripts: install scripts (Python or otherwise)
register: register a release with PyPI
sdist: create a source distribution (tarball, zip file, etc.)
test: run the project's test suite
upload: upload distribution to PyPI
upload_docs: upload HTML documentation to PyPI
まとめ
というわけで、python3.3から使えるようになるpysetupコマンドについて述べてきました。正直まだ使えないなというレベルではありますが、3.3リリースが予定されているのは来年8月ですし、これからどんどん良くなっていくと思います。
明日は初心者向けのエントリを書いてくださる @takanory さんにお願いします。
