このBlogは移転しました。今後は aish.dev を御覧ください。

python.jp改善計画

先日、CROSS2015 というイベントで、日本のPythonコミュニティ全般についてのパネルディスカッションに参加させていただいた。

90分という長丁場で、途中でトイレ行きたくなったらどうしようなどと余計な心配をしていたが、とくにダレることもなく緊張感をもって最後まで楽しく過ごせた。会場にお運びいただいた皆様と、パネラーの皆様にお礼を申し上げたい。

この辺の話をするにあたって、python.jp の今後について、いろいろと考えることがあった。大した話ではないが、今後のpython.jpの予定についてちょっと書いておきたい。

Job Boardの作成

Pythonを本格的に採用している企業などでも、Pythonプログラマの求人というのはなかなか難しかったりするので、少しでもその辺のサポートをしたい。

掲載は無料。掲載期間は6ヶ月で、6ヶ月たったら再掲載の申し込みがない限りは削除。 人材採用企業などからの掲載はお断り。ってな感じでやろうかなと。

メーリングリストの停止

現在、Python.jpでは Mailman を使ったメーリングリストを運用している。しかし、自前のメーリングリストサービスを使っていても、特にこれといった付加価値を提供できているわけではない。また、運用負荷が高い割には、どのメーリングリストもあまり利用されていない。

ということで、現在のメーリングリストは、近いうちにGoogle groupに移行しようと考えている。メーリングリストのアーカイブはこのまま残すが、新規の投稿は停止する。

移行手順とスケジュールは、決まり次第各メーリングリストに通知する予定。

また、メーリングリストの代わりに、だれでも簡単に参加できて使いやすいChat系のサービスがあれば、使ってみたいと思っている。<https://gitter.im> あたりはgithubのアカウントがあれば無料で使えて、MarkdownでPythonスクリプトの構文ハイライトもできるし良いかなとおもうけど、Slackあたりと比べうと機能的にはちょっとさびしいか?

ドキュメント翻訳プロジェクト

さいきんあまり参加できていないが、私がコミュニティ活動として一番大事に考えているのは、Pythonドキュメント翻訳プロジェクト だ。

Python.jpを使って、もうちょっとドキュメント翻訳プロジェクトの活動や成果を可視化できるような仕組みを考えたいと思っている。

「PyJUG」の終わり

利用者にはあまり関係のない話だが、これまで、「python.jpは 日本Pythonユーザ会(Python Japan User's Group:PyJUG) が運営しています」という建前でやってきた。Python.jpは日本を代表するPythonコミュニティであり、またPython.jpを私物化するつもりはない、という意思表示のためだ。

しかし、「PyJUG」はあまり実体のない、名前だけの存在で、現在ではメンバーも定まっていない。むかしpython.jpを立ち上げた頃には10人ぐらい集まってメーリングリストでわいわい話しあったりしたが、特に目立った活動をしたりイベントを実施したりということも無い。

この実体のない「PyJUG」という名前を出しているばかりに、「PyJUGってなんですか。なんか怖い人達のあつまりなんでしょ」というような怪しい雰囲気を醸し出してしまうことが多い。

ということで、混乱を招くだけの「PyJUG」はもうやめようと思っている。今どき、Webサイトを運営するのにユーザ会は必要ないだろう。githubにサイトのソースを公開し、希望者に更新権限を付与するだけで十分だ。

Python2とその時代

宣伝が続いて恐縮だが、オライリージャパンよりPythonの解説書を上梓した。昔から、Python内部の仕組みも解説したPython解説書を書きたいと思っていて、ようやく実現した感じだ。

しかし、本書の執筆は、昔、構想を立てていたときに思っていたほどは楽しくはなかった。Python2ではなく、Python3.3以降を対象に書いてしまったからだ。Python3の型システムは綺麗に整理されてしまったし、メタクラスも扱いやすくなった。メモリアロケータは改善され、ガベージコレクションの注意点も大幅に減った。Unicodeの暗黙の変換も無くなった。私が書こうと思っていた知識の多くは、Python3では無用の長物と化した。

本書をPython2向けに書いていたら、今よりずっと多くのページ数を費やしただろう。Python3は、Python2よりも落とし穴が少なく、学習も容易なプログラミング言語だ。

そんな優れたPython3だが、「普及してないじゃないか」という声が上がっているようだ。以下、その件に関する感想を書いておく。

Python3は普及してない?

まあ、Python2に比べてば、普及してない。当然だ。Pythonは20年以上の歴史を持ち、熱心に開発され、幅広く利用されてきた。Pythonは、プログラミング史上、もっとも大きな成功を収めたプログラミング言語の一つだ。2008年末にリリースされた、若造プログラミング言語のPython3に太刀打ちできるはずがない。

一度作成されたプログラムが、大した理由もなしに別の言語や環境に対応することはありえない。時間が経てば、自然とPython2->3に移行されるというものではない。

現在、Python3がリリースされてから、5年ちょっと。Pythonが最初にリリースされてから5年経った頃というと、Python1.4とか1.5とかの頃だろうか。あの頃のPythonコミュニティも、まだまだ小さかった。今のPython3ユーザより、当時の全Pythonユーザの方が少ないのではないだろうか。comp.lang.pythonに流れるメールを全部読んでも大した量ではなかったし、開発者の数もわずかだった。リリースから10年以上たった2003年、私はPyCon USに遊びにいったが、その頃でも、参加者の数はたしか400人程度だった。

プログラミング言語の普及というのは、時間がかかるものだ。2000年代後半にも、いろいろなプログラミング言語が登場してきた。その中で、Python3以上のユーザを獲得した言語はどれだけあるだろうか?

issubclass(Python3, Python)?

同じ「Python」の名を冠してはいるが、Python3は、やはりPython2ではない。異なるプログラミング言語だ。Pythonはこれまで大きな成功を収め、巨大なエコシステムを築いてきた。沢山のモジュールが開発され、ほとんどのLinuxにはデフォルトでインストールされている。利用者に見えないところで、いろんなPythonアプリケーションが動いている。Windowsのシステムディレクトリには、いつの間にかPythonxx.dllがインストールされている。

Python3はPython2と互換性がないので、このエコシステムをそのまま利用することはできない。ほとんどのPython2モジュールは、Python3でも使えるようにするには修正が必要で、Python2と3両方で使えるようにするのは大変な作業だ。Python2専用か、Python3専用のどちらか決めてしまったほうが、はるかに簡単になる。

そういう意味で、Python2コミュニティと、Python3コミュニティは「分断」される。これから開発される、Python3用のモジュールやアプリケーションは、Python2コミュニティでは利用できないだろう。また、Python2だけを利用するユーザは、Python2専用のモジュールを開発するだろう。後知恵だが、Python開発者たちはPython2/3共用アプリの開発コストを低く見積もりすぎていた。Python3は、Python2という巨大なライバルを相手に、自分の陣地を獲得しなければならない。これには、まだ時間が必要だろう。

Python2の落日

Python2は、未だに隆盛をきわめているが、その未来は明るくはない。御存知の通り、Python2の開発は終了しており、今後、Python2に機能追加などが行われることはない。結果として、Python開発チームは、とてもポピュラーなプログラミング言語を「殺し」、かわりにPython3という、新しいプログラミング言語を開発することを選んだ。

Python3なんかいらない、Unicodeなんか使わない、というユーザのいらだちは理解できる。Python2は十分現役で、そのまま使い続けるのに何の問題もないのに、お前のアプリ・モジュールは時代遅れになるから書き直せ、と言われてしまう。Pythonを単にツールに利用しているだけの人たちにとっては、迷惑なことだろう。

とはいえ、Python2は、非常に広く普及したので、本当に消えてなくなるまでには長い時間がかかるだろう。現在、bash などのシェルがこれだけ普及していても、移植性があるスクリプトを書くときには /bin/sh 用のスクリプトだけで書いたりするが、そんな感じで、/bin/python に Pyton2 がインストールされ続けるのかもしれない。そうなると、Python2の利用者が目に見えて減ることは無いのかもしれない。

Python3のエコシステム

今、Python2を使っているなら、焦る必要はない。いまあるPython2とライブラリで目的を果たせるなら、当面、Python2を使い続けるのは悪いことでもなんでもない。Python2の方が好きなら、全力でPython2をサポートするのもよいだろう。

しかし、分断されたPython2/3を統合するには、Python3のエコシステムを整備するしかない。Python3を強化し、Python2からの移行コストより、メリットが大きいことが明らかになるようにしなければならない。そのためには、ユーザがPython3を使い、改善に協力することが必要だ。

(ちなみに、個人的には、PEP 3003 Python Language Moratorium は間違いだったと思ってる。追いかけて欲しければ、全力で逃げるべきなのだ)

Python2か、Python3かで迷うなら、Python2を使うのも良いだろう。その昔は、Perlを使うか、Pythonを使うかで迷ったものだ。多少のリスクは覚悟した上で、Pythonを使っていた人たちがいて、その積み重ねがPythonの今日を作り上げた。同じ積み重ねが、Python3でもまた繰り返されると信じて、私は今日もPython3を起動している。

書籍 Python文法詳解 (※表紙は犬ではありません)

このたび、オライリージャパンよりPythonの解説書を出版させて頂くこととなった。表紙絵の動物は、犬ではなくアルプス・マーモットだ。

長年のあいだ、オライリージャパンの某氏にはPython本を書け書けとせっつかれていて、そのたびにうーんむにゃむにゃと誤魔化していたが、ついに書いたった。古い借金を返したようで、スッキリした。慶賀のいたりだ。

この本はPython3言語の解説書で、本人としては、プログラミング経験のある人なら読めるように、というつもりで書いている。Pythonの歴史から入って簡単なチュートリアルに進む、という正統派ストロングスタイルのプログラミング解説書だ。

しかし、本書を読むだけでは、Pythonプログラミングはマスターできない。Python3言語の文法とリストなど基礎的な組み込みオブジェクト、Pythonの実行モデルなどを中心に解説しており、Pythonの標準ライブラリについてはほとんど解説していないからだ。この決断のおかげで、本書は1000ページを超えるような電話帳まがいの本になることを回避できた。

しかし、その分、Pythonの式や構文についてはしっかリ解説できたと思っている。Python名前空間ガベージコレクションなど、標準ドキュメントを読んでいるだけではなかなか理解しにくい、Pythonの実行モデルにかんする説明も記述できた。結構細かい点も深堀りしているので、それなりに経験を積んだPythonistaでも、本書から一つ二つぐらいは得るものがあるのではないかと思う。

Pythonにもいろいろ取り入れられていく過程で、説明が一箇所にまとまっておらず、ライブラリリファレンスと言語リファレンスと関連PEPに分散してしまっていたりする機能もある。そういった点も、できるだけこの本でまとめて解説するように心がけた。

私ももう20年近くPythonを使ってきたが、その中で、「この辺を押さえとくと、Pythonへの理解が深まるよ」というポイントを押さえて解説できたと思う。Pythonの活用に役立てていただきたいと、けっこうマジに願っている。

PyCon JP 2014会場

なお、この本は2014/9/18からの販売ではあるが、PyCon JP 会場では、9月13日のオライリーブースでフラゲ可能となっている。この販売は 9月13日 だけで、*14日には出展されていない* ので、ご注意を。

また、PyCon JP会場では、私は9月14日のジョブフェア会場 UNCOVER TRUTHブースに参加する。そこで本書の立ち読み&質問受付なんかもできると思うので、気軽にお声がけください。

Python 3.4 で追加されたモジュールのPyPIパッケージ

Python 3.4の新規モジュール で、Python3.3以前用のパッケージが用意されているモジュールの一覧。


モジュール名 対象バージョン URL


enum 2.4 〜 3.3 https://pypi.python.org/pypi/enum34

asyncio 3.3 〜 <https://pypi.python.org/pypi/asyncio >

pathlib 2.7, 3.2 〜 <https://pypi.python.org/pypi/pathlib >

statistics 3.1 〜 https://pypi.python.org/pypi/stats

Python 3のexcept文

Python3で例外をキャッチすると、例外オブジェクトを代入した変数は削除される

>>>a =100
>>> a
100
>>> try:
... 1/0
...
... except Exception as a:
... pass
...
>>> a
Traceback (most recent call last): File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined 

PEP-3134の__traceback__ 対応かぁ

Python 3.4 のオブジェクト開放処理

Python Advent Calendar 2013 の六日目です。Python3.4 で導入された PEP 442 -- Safe object finalization の解説を簡単に。

Pythonのメモリ解放処理

Pythonでは、処理中に使われなくなったオブジェクトを検出し、自動的に開放するようになっている。他のオブジェクトから全く参照されておらず、Pythonインタープリタからアクセスできなくなってしまっているオブジェクトは、不要なオブジェクトとして削除される。

例えば、

>>> class Spam:
...     pass
...
>>>
>>> obj = Spam()
>>> obj = None

では、最初に作成した Spam オブジェクトは、obj という名前で参照できるが、次の行では obj = None と別のオブジェクトを指すように変更されると、もうPythonインタープリタから参照できなくなる。このため、Pythonはこの Spam オブジェクトは不要となったと判断し、削除する。

循環参照

他のオブジェクトからの参照があっても、孤立したグループ内でのみ参照されているなら、そのグループのオブジェクトは開放される。

>>> class Spam:
...     pass
...
>>>
>>> obj1 = Spam()
>>> obj2 = Spam()
>>> obj3 = Spam()
>>> obj1.obj2 = obj2
>>> obj2.obj3 = obj3
>>> obj3.obj1 = obj1
>>> obj1 = obj2 = obj3 = None

この例では、obj1obj2obj3 オブジェクトは、それぞれお互いへの参照をメンバとして持っている。このように、複数のオブジェクトがループ状にお互いを参照することを、*循環参照* と呼ぶ。

この循環参照は、最後の obj1 = obj2 = obj3 = None で変数 obj1, obj2, obj3 が別のオブジェクトを参照するように変更されたので、どのオブジェクトもPythonインタープリタからはアクセスできなくなってしまった。Pythonは、このようにお互い同士では参照していても、外部からはアクセスできなくなってしまったオブジェクトも不要と判断し、開放する。

しかし、これまでのPythonでは、この循環参照の開放には制限があった。

>>> class Spam:
...     def __del__(self):
...         print('deleting...')
...         global dont_kill_me
...         dont_kill_me = self

このように、特殊メソッド __del__() を持つオブジェクトが循環参照を構成する場合、開放の対象外となっていた。これは開放のときに __del__() メソッドを呼び出すと、その呼出の順番によってはすでに解放済みのオブジェクトを参照してしまったり、また自分自身を再び外部から参照可能な状態にしたりしてしまう可能性があったためだ。

上の例では、__del__()グローバル変数 dont_kill_me にオブジェクトを保存しているので、Spam クラスのインスタンスは削除されることはない。

PEP 442

Python 3.4以降では、PEP 442 でこの点が改善され、__del__() を持つオブジェクトが循環参照に含まれていても、開放されるようになった。従来のメモリ解放処理に比べて、いくぶんか処理量が増加しているが、現在ではPythonガベージコレクションが実装された西暦2000年頃に比べてコンピュータのハードウェア環境は大きく進歩しており、この程度はあまり問題とはならないだろう。

PEP 442での変更で、以下の点は気にしておいたほうが良いだろう。


循環参照の一部に、先ほどの

>>> class Spam:
...     def __del__(self):
...         print('deleting...')
...         global dont_kill_me
...         dont_kill_me = self

のようなオブジェクトが含まれている場合、オブジェクトは参照可能な状態に戻るので開放はされない。しかし、この場合開放はされなくても、循環参照を構成する、全てのオブジェクトの __del__() メソッドが呼び出される。つまり、Python3.4以降では、__del__() が呼び出されたとしても、必ずオブジェクトが開放されるとは限らなくなった。


上の例で、すでに __del__() が呼び出されてしまったオブジェクトが再び参照不能になったときでも、もう __del__() メソッドは呼び出されない。__del__() が呼び出されるのは、ただ一度だけである。

(注: 例外として、 https://mail.python.org/pipermail/python-dev/2013-June/126834.html などのケースで複数回呼び出されることもありうるが、現実問題としてあまり考慮する必要はないだろう)

開放されない循環参照もある

PEP 442 で、すべての循環参照が開放されるようになったわけではない。循環参照に含まれるオブジェクトがPythonのクラスから作成したインスタンスだけであれば開放されるが、C言語で実装された型のオブジェクトが含まれる場合、従来と同じように開放されないケースもある。

油断は禁物

Python2で gc モジュールが実装されて以来、__del__() メソッドは実装するメリットよりもデメリットのほうが大きいと考えられ、できるだけ使わないようにするのが一般的だった。お陰で with ステートメントなどの機能が大きく進化することになったが、ここで再び __del__() のデメリットが少なくなったことで、__del__() にいろいろな処理を詰め込みたいと思う人もいるかもしれない。

しかし、__del__() のデメリットは、循環参照時に開放されないことだけではない。__del__() が呼び出されるタイミングは予測できないし、全く呼び出されないかもしれない。先程の例のように、呼び出されたとしても本当に開放されたとは限らないし、マルチスレッドアプリケーションでは、どのスレッドで呼び出されるかも予測できない。__del__() の活用には、いろいろと難しい点が残っている。

したがって、Pythonプログラミングのガイドラインとしては、「できるだけ __del__() に依存しない」というのは、依然として有効だと考える。くれぐれもC++のデストラクタと同じような使い方が出来ると思ってはならないのである。