最近はPythonのC拡張を書いていたりするので、覚えている範囲でハマった点を説明します。C拡張を書き始めるには、基本的にPython インタプリタの拡張と埋め込みをみて、あとは見よう見まねで書きながらPython/C API リファレンスマニュアルを見とけばOKです。
やると良いこと・ハマったこと
引数はDECREFしてはいけない
Pythonのドキュメントをよく読んでないのも悪いのですが、どうやらPythonからCで書かれた関数を呼びだされたときに渡ってくる引数はDECREFしてはいけないようです。 Python組み込みのAPI用意している分にはドキュメントにNew Referenceとか書いてあるのでそれをみて判断すればいいです。
DECREFの引数は2回以上評価される可能性のあるマクロなので変数のみ渡す
同じくDECREF周りですが、Py_DECREFとかはマクロなので引数が複数回評価される可能性があります。というかされます。なのでPy_DECREF(PyObject_CallFunction(...))みたいなことをすると死にます。
cpythonのソースコードは手元に持っておく
正直ドキュメントを参照するよりかはソースコード直接読んだほうが早かったりするので、cpythonのソースコードは手元においておきましょう。というかPythonのスクリプトを書いててもドキュメントに書いてない感じのこととか、曖昧な感じがする点があったりして、そういうときにソースコード手元に持っておくとすぐ確認できて便利です。
デバッグ版Pythonを使う
多分これは自分が高速化のために文字列の可変長配列を自分で持っていたりとか、そういうことをしているからだと思いますが、メモリ周りのエラーで苦しみました。ひたすらSegmentation Faultします。デバッグ版のPythonを使うとメモリまわりでチェックが走るのである程度メモリエラーを検出できます。Pythonは自前でメモリ割り当てを行なっている関係なのか、Valgrindとかを使ってもあんまりInvalid writeみたいなのは検出できなかったです。(Valgrindの仕組みとかよくわかってない)
デバッグ版Pythonのビルドの仕方はPython Developer's Guideに書いてあるのでこれを見て--with-pydebugをつければOKです。自分はpyenvを使っているので、そのプラグインの python-build を改造してデバッグ版ビルドができるようにしました。そのうち整理してPull-Request投げてみるかも。
yepをつかってプロファイリング
yepはバックエンドでgperftoolsを使ってプロファイリングをしてくれるモジュールです。普通にPython付属のプロファイラだとPythonのコードしかプロファイリングできないので、このモジュールを使ってどこが遅くなっているのかを調べます。
よくわかってないこと
GC周り
どうやらオブジェクト内に外のオブジェクトを含み場合は、普通はGCを有効にしなければいけない感じのようなのですが、別に自分が書いているクラスはユニコード文字列とファイルライクオブジェクトなので、GC周りのフラグを立てていません。GC-awareな書き方は、多分ドキュメント見ればわかるんだろうと思いつつ、よくわかってません。
Windows NativeのPythonでC拡張をビルドする方法を説明します。みなさん普通は WindowsではPythonなんて使わないのか、あんまり情報が無いんですよね……
Windows SDKをインストールする
C拡張なのでCコンパイラが必要なので、コンパイラをインストールします。MicrosoftはVistual Studioを売っているのでそれを買えばコンパイラがついてきます。また、無償版のExpress Editionをインストールしてもコンパイラがついてきます。
C拡張をうまいことビルドするために、distutilsはVS2008のコンパイラに対応するように書かれています。UNIXだと適当にPATHからコンパイラを探してくれば良いのに、なぜWindowsだとdistutilsがVS2008のための特別な処理を入れているかというと、コンパイラの場所がWindowsだとPATHに入っていなかったりして、レジストリから推測しなければならないからです。残念OSですね……
レジストリからコンパイラの場所を推測する関係で、より新しいバージョンのVSには対応できていません(レジストリエントリの場所が違うので)。そして、最近対応しているVS2008の(一部のVC++ 2008の)Express Editionのダウンロードができなくなったようです。([Python-Dev] VC++ 2008 Express Edition now locked away?)コンパイラが入手できないのではdistutilsが対応するまでWindows上ではC拡張をビルドすることができません。
案ずることはありません。まだ道はあります。我々が欲しいのはコンパイラのみです。 MicrosoftはIDEがついてこないコンパイラ単体も配布しています。それがWindows SDKです。ちょっと前までPlatform SDKという名前だった気がします。VS2008のバージョンと互換性があるのはMicrosoft Windows SDK for Windows 7 and .NET Framework 3.5 SP1という Windows SDKでこちらはまだダウンロード可能です。こちらをインストールしましょう。
vcvarsall.batをつくる
この状態でpython setup.py buildをやるとvcvarsall.batがないという趣旨のことを言われてビルドできません。このvcvarsall.batはVS2010と互換性のあるバージョンのWindows SDKだとついてきているのですが、2008と互換性のあるバージョンのSDKだとついてこないようです。中身は単純で現在のシステムが64bitか32bitかによって(これは引数でも指定できるようです)使うコンパイラを選択するという単純なバッチファイルです。コンパイラの選択もほかのバッチファイルを呼んでいるだけですので、自作しましょう。
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.batを作成します。32bit版Pythonを利用している場合は、:
@call "%~dp0bin\vcvars32.bat"
という行を、64bit版の場合は:
@call "%~dp0bin\vcvars64.bat"
という行を一行書いて保存します。64bit版Windowsではない場合は適宜Program Filesを読み替えてください。
これでC拡張をコンパイルできるようになります。
より新しいバージョンを利用する方法
より新しいバージョンのコンパイラを利用する方法もあります。残念ながらdistutilsは(Python本体がコンパイルされたバージョンである)MSVC2008のコンパイラしか認識してくれないので、その部分をスキップしてPATHから探すようにします。
環境変数にMSSdkとDISTUTILS_USE_SDKという変数を追加して下さい。値はなんでも構いません。これによりdistutilsはパスが通っているところからcl.exeやlink.exeを探します。
この方法の注意点は、Cygwin上でWindowsネイティブのPythonを利用してC拡張のコンパイルをしようとすると、CygwinのGCCのlink.exeが利用されてしまうことと、Python本体と依存するライブラリが変わることです。後者によりpy2exeなどでexeにして配布するときに、実行環境で再頒布可能パッケージがなくて実行できない可能性があります。 (再頒布可能パッケージをインストールすれば実行可能です)
社会人になるであろうちょっと手前で税金について調べなければいけなくなったので、必要であろうところだけ書く。正確なことはわからないので、詳しくはタックスアンサーを見ればいいと思う。というかタックスアンサーを最初から最後まで全部読めばだいたい分かる話。
ちなみに会社に入ると使用者側がそこら辺をやってくれる。なので大体の人はあまり関係ないらしい。確かに自分の両親に聞いてもあまり良くわからない感じだった。
税金
ざっくり言うと「(所得 - 所得控除) * 税率 - 控除 - 税額控除 = 所得税額」になっている模様。東京都しか知らないけれど住民税もほぼ同じ構図になっていて、少しずつ額や比率が違う。
所得
所得はいろいろ種類があるらしい。その種類によって税金のかかり方が変わったりするみたいだが、アルバイトの場合は給与所得になるはず。なんかの賞金とかだと一時所得になるのだろうか。
所得控除
得た所得に対して「こういうことに使った額については税金かけないよ」とか「あなたがこういう事情の人だったら税金かけないよ」というのが控除。いろいろ種類があるけど、一覧は所得金額から差し引かれる金額(所得控除)を見る。
関係有りそうな控除はこんな感じ
- 基礎控除
- まずみんな一律で38万円は控除される
- 医療費控除
- 病気や怪我をして医療費がかかると控除される
- 給与所得控除
- 給与所得がある場合にその額に応じて控除される
- 社会保険料控除
- 年金払ってると控除される
- 勤労学生控除
- 苦労している学生だと控除される
- 扶養控除
- 誰か養っていると控除される
ただ、なんか色々制限があって、例えば医療費控除は10万超えないと控除されないし、しかも保険がおりるとその分は控除対象から外れる。他にも勤労学生控除とかアルバイトしすぎて180万とかだと稼ぎすぎて逆に勤労学生じゃないということで控除対象外になる。
あと、親から「いい?何があっても103万より多く稼いじゃダメよ」ということを言われている人もいると思うが、これは扶養控除の対象になるのが「給与所得から給与所得控除を引いた額が38万円以下の人」なので、そこから逆算すると103万より多く稼ぐと扶養控除の対象にならずに控除額が減って親の税金が増えるためだ。
税率・控除
所得から所得控除を引いて残った額(課税される所得金額)に対して、XX%の税率をかけると(基本的には)税金の額になる。ここよくわかってないが、日本は超過累進税率という制度らしく、その課税される所得金額があるラインを超えると、その超えた分に対して課税されるという仕組みらしい。
よくわからないので、そこら辺は所得税の税率を見ましょう。この表をみて計算すれば一発でわかる。
先ほどの親の税金は「失われた控除額 * 税率」分だけ増えることと思うので、大学生で親の税率が23%だとすると「63万円 * 23% = 15万円弱」、33%だとすると「63万円 * 33% = 21万円弱」の税金が増えることになるのだと思う。ひぃー!
税額控除
最後になんか税額そのものから引ける控除があるが、あまり関係ないと思う。eTaxで確定申告をやると3000円ぐらい控除される。
税金の納付・還付
税額を計算した結果の額だけ納めることになるが、実際は給与から源泉徴収という形で毎月引かれてたりする。この源泉徴収はみなしでだいたい最終的にこれぐらい税金払うことになるだろう、という感じで納めるものらしい。なので最終的な額と食い違う場合があるので年末調整とかして税額を確定させる。多く払いすぎていた場合は還付される。
住民税
住民税もだいたいおなじ仕組みで計算されている。ただちょっとずつ額とか割合が違うのでちょっとずつ変えて計算すれば良い。
よく言われる103万の壁、130万の壁とは
基礎控除 + 給与所得控除の最低額 = 103万。それ以外に控除がない場合は、それ以上稼いだら所得税が発生する。どちらかと言うと先にでた親の扶養から外れるのが大きいのだと思う。
基礎控除 + 給与所得控除の最低額 + 勤労学生控除 = 130万。学生の場合は勤労学生控除も適用できるので130万を超えない限りは所得税が発生しない。しかし、130万を超えた瞬間に勤労学生控除が適用できなくなるので一気に所得税が発生する。
ちなみに東京都の場合は、基礎控除 + 給与所得控除の最低額 = 98万、基礎控除 + 給与所得控除の最低額 + 勤労学生控除 = 124万なので、それぞれ同じような感じで住民税が発生する。税率が一律10%なので、所得税よりも高くついたりする。
あと、130万の壁を突破すると131万ジャストで稼いだときよりも、130万ジャストで稼いだときのほうが手取り収入が多いという現象が起こる。
つらぽよ……
調べてたら130万超えると親の医療保険入れないらしいので自分で国民健康保険はいらないといけないらしい。住民税で4,5万払うことになってうわぁ……と思ってたら国民健康保険料が二桁万円いってて僕の口座残高が悲しいことになることが予想される。
追記
どうやら国民健康保険料の計算を間違えてたばかりか、そもそもアルバイト収入の場合扶養に入るかどうかの判定方法が違ったらしく、親の健康保険に入れることになった。なんか儲けた気分。ただ代わりに年金の学生特例が使えないこともわかったけどね……

Social