YAMAGUCHI::weblog

海水パンツとゴーグルで、巨万の富を築きました。カリブの怪物、フリーアルバイター瞳です。

Python3 Advent Calendar 2011 17日目 PEP 3143 Standard daemon process library

はじめに

こんにちは、Python界の情弱です。今年もアドベントカレンダーの季節がやってまいりまして、「あぁ、今年もあと少しでおしまいか」などとしみじみ感じております今日この頃ですが、皆様におかれましてはいかがお過ごしでしょうか。
さて、今年はPython3 Advent Calendarということなんですが、Python 3.2まではLanguage Moatoriumということもあって色々な機能がPython 2.7にback portされているので、僕からはPython 3.3から導入予定のPEP 3143を紹介しようと思います。

参考リンク

PEP 3143: Standard daemon process library

そもそも何故この機能が提案されたかをPEPを読んでまとめてみると

  • 正しく安定したdaemonを書くのはいささか複雑
  • でもdaemonなんてだいたい書き方決まってる
  • なのにいささか複雑だから結構抜けがある実装してしまう
  • 3rd party実装もあるけどこのPEPの仕様通りのものか、しょぼい実装しかない

ということで、DRY精神で標準ライブラリで提供すればよくないか?ということのようです。

参照実装 python-daemon

新しいモジュールの提案なんかのときは大抵参照実装がありますが、このPEPも例に漏れず参照実装があります。python-daemonがそれです。*1

インストールする

python-daemonをとりあえずインストール。

$ pip install python-daemon

おわり。簡単。

使う

使い方は簡単で、daemon用のコンテキストの中に処理を書くだけ、という話。試しに、5秒おきにpidとppidと時刻を表示する関数をdaemon化してみます。

# -*- coding: utf-8 -*-

import time
from datetime import datetime
import os
import os.path
import daemon

def daemon_process():
  while True:
    print( "pid: %d, ppid: %d, time: %s" % 
           (os.getpid(), os.getppid(), datetime.now()) )
    time.sleep(5)

working_dir = os.path.abspath(os.path.dirname(__file__))

context = daemon.DaemonContext(
  working_directory = working_dir,
  stdout = open("stdout_file.txt", "w+"),
  stderr = open("stderr_file.txt", "w+")
)

if __name__ == '__main__':
  with context:
    daemon_process()

これを実際に起動してみると

$ python test_daemon.py
$

お、普通のスクリプトと違ってプロンプトが戻ってきました。さらに、test_daemon.pyのディレクトリに行くと

$ ls test_directory
test_daemon.py    stdout_file.txt    stderr_file.txt
$ tail -f stdout_file.txt
pid: 4501, ppid: 3676, time: 2011-12-17 21:04:05.846464
pid: 4501, ppid: 3676, time: 2011-12-17 21:04:10.846690
pid: 4501, ppid: 3676, time: 2011-12-17 21:04:15.846927
pid: 4501, ppid: 3676, time: 2011-12-17 21:04:20.847200
pid: 4501, ppid: 3676, time: 2011-12-17 21:04:25.847490

標準出力が無事に取れています。こんなに簡単にdaemonにできるのは便利ですね。

Python 3.3ではどうか

Python 3.3のビルド

現在開発レポジトリのdefaultは3.3の開発版扱いなので本家のレポジトリをcloneしてきてビルドする。

$ hg clone http://hg.python.org/cpython
$ cd cpython
$ ./configure --prefix=/opt/python/3.3
$ make
$ make install
$ cd /opt/python/3.3/bin
$ python3
Python 3.3.0a0 (default:d22c99e77768, Dec 16 2011, 00:01:44) 
[GCC 4.2.1 (Apple Inc. build 5659)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import daemon
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named 'daemon'

まだdaemonが実装されてねえ!!早くしてくれ!

おわりに

まだ実装はされていないpython-daemonですが、ツール屋さんな僕にはとても嬉しい機能なので早く標準化してください!
明日は世界の小宮さんです (@tk0miya) 宜しくお願いいたします。

おまけ

先日 @doloopwhile さんがPythonの日本語ドキュメントの話をしていましたが、僕もそれなりに翻訳しているので、宜しければブログの左側にあるメニューよりご覧ください。以上。

*1:「よし、開発レポジトリを探すぞ!」と思ってGitHubに行くとはまります。同じ名前の有象無象のレポジトリがたくさんあります。ここにオリジナルがあったという残骸があります。 http://anonscm.debian.org/bzr/bzr/python-daemon/