Python3も3.3になり性能も向上して、移行が順調に進んできているように見える。それを考慮して最近Python3系と2系の互換性確保を見直した。

ひとことでいうと「Python3中心」にした。

今までの手法

基本的に3系と2系の互換性確保は「単一ソースコード」でやっていてそれは今も変わらず。

で、今までは Python3とPython2の中間 のコードを書いていた。組み込みの関数のリネームなどはしない、というような(例えば zipizip で上書いてしまうとか)。ただこの手法だといざPython2系のサポートをdropする場合に処理的にもコード的にも無駄が多くなる。

今の手法

rayscompat.py では以下のような方針とした。

  • Python3中心。
    • Python3の時に効率的に動作する
    • Python2のサポートドロップ時にソース修正が容易

なのでガンガンPython2の関数はPython3に置き換える。( mapimap にしてしまうなど ) 大まかには compat.py のコメント通り以下のようなコーディング。

  • 文字列は strbytes を使う。

  • range , map , zip などはイテレータを返すものとする。

  • コレクションの列挙は iter_items などの関数を通す。

  • iterator.next() の代わりに next 関数を使う。

  • クラスは object の代わりに compatobject を継承する。

    • __str__ , __nonzero__ , __cmp__ など廃止・仕様変更されたメソッドは Python3の仕様で実装する。 compatobject が Python2の場合は自動で変換する。
  • リネームされたモジュールのimportは compat_import メソッドを使う。

    • 例: compat_import(py2="email.MIMEMultipart", py3="email.mime.multipart")
      • このようにするとPython2でも email.mime.multipart でアクセスできる。
  • urllib は複雑にリネームされているので、 python2用 urllib を作ってしまう。

    • Python2でも普通に import urllib.request のように書ける

キモは compat_import かなと。

そうすると、以下のような感じでほぼPython3のみ対象としたのと同じソースコードになる。Python2サポートdrop時は単純なソースコード置換でいけるはず。

 1import urllib.request
 2compat_import(py2="cookielib", py3="http.cookiejar")
 3
 4class Html(compatobject):
 5  def __init__(self, text):
 6    if isinstance(text, bytes):
 7      text = text.decode("utf8")
 8    self.text = text
 9
10  def __str__(self):
11    return self.text
12
13cookie_jar = http.cookiejar.MozillaCookieJar()
14handlers = [urllib.request.HTTPCookieProcessor(cookie_jar)]
15opener = urllib.request.build_opener(*handlers)
16html = Html(opener.open("http://www.google.co.jp/").read())

ソースコードの寿命をのばすためにもボチボチこの方針で書き変えていくつもり。


放置して久しいこのブログ、やっと重い腰をあげていろいろ手をいれた。

  • HTML5化
  • ブログシステムを入れ替え

silkylog

このブログはxreaのレンタルサーバで動かしているのだけど、しばらく見ないうちにxreaもサーバがすごく増えて、新しいサーバではpython2.7.5が使えるようになっていた。

なので自作のwebフレームワーク rays を使った新しいブログシステム silkylog に移行した。silkylogはpython3.3でも動くのでしばらくは安心。これまで使っていたのはpython2系でしか動かないし、かといってpython3対応させる気力も起きないしでどーしたものかと思っていた。

流行に乗ってOctpressとかにしようかなあ、と思いつつせっかく作ったのだしと思って。ただなんとなく悔しかったのでsilkylogにOctpressと同等の完全に静的なサイトを出力できる機能も付けた。

さらにこれまでのDBベースからファイルベースに変更した。Blosxomみたいにファイルを直接検索してもいいんだけどタギングを考慮するとそれはそれでめんどくさいので、インデックス情報のみsqliteで保持するような中途半端なカタチに。

手前味噌ながらraysの機能を余すところなくつかって、シンプルに作れたと思う。

html5化(デザイン)

ようやくhtml5に。デザインも見直し。シンプルでよいデザインにできた・・・と思う。cssはscssでまとめた。 レスポンシブルデザインにも対応。コメントはDisqus、シンタックスハイライトはgoogle code prettifyと外部だよりに。

マークアップはreStructuredTextに統一した。普及度を考えるとmarkdownなのだけどやはりmarkdownは表現力が低くて。いろんな方言が乱立してるし、独自に拡張をするしくみに乏しいので使いづらかった。

ここのところ、Pythonかどうかに関わらずドキュメントはsphinxで書いているので、日常的に書いているのはreStructuredTextが圧倒的だし、ディレクティブが簡単に作れるのもよい。


ともかく、これでしばらくは手をいれなくてすむ・・・はず。


なんとなく思い立って、Windows用コマンドラインランチャー「iceberg」をリリースしました。設定はLuaな設定ファイルのみという硬派なソフトなのでエンジニア向けです。

ダウンロードとドキュメントは以下から。とりあえずWindows64bit版しか今はないです。

image

これはなに?

シンプルなコマンドライン型ランチャーです。かなり昔から自分用につくって細々使い続けてきたものなので、ソースは割と悲惨です。何回か頑張って書き直しましたが気力が持ちません。使い続けているだけあってそこそこ安定しているはずです。一方あんまり使っていない機能はしらないうちに動かなくなっているかも知れません。というか動かなくなっていたので公開にあたってちょこちょこ直しました。

開発に至った思想は以下のような感じです。

  • 旧craftlaunchを使っていたのだが以下の不満があった。
    • アイコンくらいほしい。

    • 引数を渡すために ; と書かなくてはならないのが嫌だった。

    • 拡張言語がなにかしらほしかった。

      • そうこうしているうちにPythonで拡張できるcraftlaunchが出てきたが なんとなく自分の思ってたのと違った
    • 設定をバージョン管理システムで管理したかった

      • そうこうしているうちに(ry なcraftlaunchがでてきたんですが…
    • 見た目がもう少し派手でもいいんじゃないかと…

    • 曖昧マッチ(firefoxにffでマッチするような)がほしかった

特徴としては以下かなと。

  • Luaで拡張できる

  • 「普通に」引数が渡せる。ダブルクオーテーションで囲えば空白もOK

  • 前方一致、部分一致、あいまい検索ができる

  • migemo対応

  • 簡易ファイラとしても動作

  • 外部プログラムとの連携機能あり

    • 外部プログラムからicebergの入力欄に文字を入れるとか
  • 空白にもコマンドを割り当てられる

技術的な話

実装言語はC++ & Luaです。なぜLuaかというとやはり組み込みやすさが段違いで、拡張言語としての扱いやすさはPythonより高いと思っているからです。そろそろC#に移行しないといけませんかねえ…。

工夫した点というかハマったのは使用しているGUIライブラリであるfltkの挙動ですね。マルチバイトフォントのレンダリングがとてつもなく遅いのです。なのでリスト表示部分は自前でwin32のAPIを呼んでいます。コマンドラインランチャはサクサク感がウリですから、もたるのはちょっと。ただ入力欄はfltkのままなのでここに長い日本語を一気にぶち込むと少し固まります。とはいえ、こうしてハマってもすぐソースがよめるのがfltkの良いところだと思います。

あと、内部的にutf8で処理してます。はっきりいって無駄が多いんですけど、utf8はいろんなライブラリ混ぜるなら楽ですね。fltkもutf8なら日本語通るし、Luaもutf8なら日本語OK。PCの性能もあがっているので文字コード変換が増えてもつくりが楽だしこれでいいかなあ、と。

結構前から64bit Windowsの環境しかもってないのですが、もちろん昔は32bitで動かしていたのでたぶん、MinGWで git clone , ./tool/install_requires.sh , make dist , make package とやればコンパイルできる…はず。

一応OS依存部分は分岐させてあるので、その気になればMacとかLinuxにも移植できる…はず。