SlideShare a Scribd company logo
"Continuous Publication" 
with Python: 
Another Approach 
This presentation will be in JAPANESE
英語必須と勘違いした orz
発表者自己紹介 
• 宮川大輔 (@amedama) 
• 株式会社 mokha 取締役 
• 「もか」 (もくは) 
• 前職: Google Inc. (U.S, Android部門)
Continuous Publication 
継続的出版
造語
「書籍」ビルドシステム 
を作ってみた
「書籍」ビルドシステム 
Griflet 
• PDF, epub, InDesign, … 
• Re:VIEWを採用 
• 同人誌~商業書籍の「ビルド」 
• 「書籍執筆」を支援
Re:VIEW 
• 書籍執筆に強い軽量マークアップ言語 
• https://github.com/kmuto/review 
• @kmuto, @takahashim, @kdmsnr, … 
• TeX, epub, HTML, InDesign, … 
• 参考図書: https://github.com/TechBooster/FirstStepReVIEW
Grifletのきっかけ 
• 同人誌『Effective Android』 
• C84 (2013年 夏コミ) 
• 著者22人, 184ページ 
• Re:VIEW + GitHub → すごい! 
• だが…… 
TechBooster代表 
@mhidaka
ビルド失敗に 
気づかない
ビルド失敗に気づかない 
• 執筆中はビルド結果に無頓着なことが多い 
• 「HTMLが作れてるのでコミット」 
→PDFのビルドが成功するとは限らない 
• Continuous Integration 環境が( ゚д゚)ホスィ…
自分で作った
(2) WebHook 
(1) commit 
(3) Build Req. 
(4) Build 
(6) Download 
(5) Notify 
Linux 
Re:VIEW
デモ
……のサブセット
"Continuous Publication" with Python: Another Approach
"Continuous Publication" with Python: Another Approach
"Continuous Publication" with Python: Another Approach
"Continuous Publication" with Python: Another Approach
"Continuous Publication" with Python: Another Approach
割と手探り 
• Django, Celery初めて 
• 「virtualenvって何 (́・ω・`)」 
• 当初、1プロジェクトのみサポート
同人誌 → 商業書籍 
• 『Effective Android』(TechBooster) = 同人誌 
『Effective Android』(達人出版会) = 電子書籍 
『Effective Android』(インプレスジャパン) = 紙商業 
• 共著者 22人 → 33人 
• epub もサポート 
• Re:VIEW偉大 (>ヮ<)
次のお題 
• TechBooster @ C85 (2013年 冬コミ) 
• 4冊同時刊行 
• 合計1書籍 -> 合計5書籍
ビルドが 
たまに止まる orz
「たまに止まる」問題 
• たまに … 1週間に一回とか 
• 原因: Celery + GitPythonの組み合わせ 
• 根本原因は未解明 
• 迂回策: subprocess.Popen + git
Re:VIEWが暴走する
Re:VIEW暴走事件 
• Re:VIEW側のバグ (正規表現が無限ループ化) 
• Celeryのタイムアウトも効かず……
動かなくなったら 
すぐ教えて欲しい
Zabbix 
• OSSの監視ソフト
C85 も無事に終了
そこそこ評判が良い
クチコミヽ(=́▽`=)ノ
クチコミ 
• 「友人の友人」のプロジェクトも扱い始める
……えっ (゚Д゚)
知らない人の 
Re:VIEWプロジェクト
is 脅威
あるいは
Re:VIEW is 脆弱性
「Re:VIEWは脆弱性」問題 
• Re:VIEWではRubyコードで命令を拡張出来る 
• OSコマンドインジェクションそのものじゃね? 
• サンドボックスが( ゚д゚)ホスィ…
• Immutable Infrastructure 
• 「軽量VMでOSを囲って実行 -> 廃棄」 
• ぴったり(●́ω`●) 
• ……と油断していると
_人人人人人人_ 
> 突然の死 < 
‾Y^Y^Y^Y^Y^Y‾
Dockerは不安定? 
• あくまで過去形 = 今は比較的安定している 
• 実際、Dockerのバグには何度か出会った 
• 自分のミスという部分も多々あった 
• モニタリング大事
(2) WebHook 
(1) commit 
(3) Build Req. 
(4) Build 
(6) Download 
(5) Notify 
Linux 
Re:VIEW
(2) WebHook 
(1) commit 
(3) Build Req. 
Re:VIEW 
(4) Build 
(6) Download 
(5) Notify 
Linux
C86 (2014年 夏) 
• またもやTechBooster 
• 他サークルの同人誌も
粛々と開発
開発上の課題
「片手間」開発
「片手間」開発 
• 長いスパンで少量の実装をちまちま 
• 一人で「1ヶ月に2~3日。まとめて」
そして忘れる 
• 設計・実装・運用の詳細を、忘れる 
• どのような問題が発生していたかを、忘れる 
• ユーザフィードバックを、忘れる 
• 自分が何を達成したいのかまで、忘れる 
• しばしばここで作るのをやめてしまう
よくあるよね
諦めない(`・ω・́)
対策を考えてみる
対策 1
メモる
対策 1: メモる 
! 
• Redmineのチケットに、メモる 
• ソースコードへのコメントに、メモる
「古くてアホくさいメモ」 
忘れるよりマシ
見るのはハズカシィ (∩∀`*)
Redmineのチケット 
• 作りたい機能、設計上の課題、未解明な点を記録 
• 現在: 合計200チケット超 (未完了100超) 
• 不定期の見直しで「思い出す」
コードへのコメント 
• 「理由」「意図」「疑問」をなるべく残す 
• 含「よく分かってないんだけど何故かこうなる」 
• 「何をしているか」のコメントは避ける 
• 整合性がとれなくなると余計に混乱する
対策 2
ログる
対策 2: ログる 
• = ログに残す 
• 「ここ通ったら、あかーん」というログも 
• コメントの代わりにログにしてしまう 
• RotatingFileHandlerでサイズを抑える 
• 注: サービス規模が大きくなったらもちろん無理
それでも見失う 
• print() になってる 
• logging.debug() って書いてる
Loggerを活用する 
• print()を避ける 
• “logging”自体 
インポートしない 
• 関数の仮引数にlogger 
• http://qiita.com/amedama/items/ 
b856b2f30c2f38665701 
from logging import getLogger, DEBUG 
from logging import NullHandler 
local_logger = getLogger(__name__) 
handler = NullHandler() 
handler.setLevel(DEBUG) 
local_logger.setLevel(DEBUG) 
local_logger.addHandler(handler) 
! 
def some_func(…, logger=None): 
logger = logger or local_logger 
logger.error(u“some_func() なう”)
「開発ログ」と「運用ログ」 
• Logging Context が与えられない 
• 1つの関数で2つのloggerを管理したくはない
テスト……?
ユニットテスト 
• モックアウトが「無駄」になりやすい 
• 「外部ツールのリアルな挙動」が問題の発生源 
• Viewについて重点的に
回帰テスト/結合テスト 
• 外部の世界: Docker, Re:VIEW, …… 
• 片手間の最中に「変わってしまう」ことがある 
• 効率的にこの変化を捉える(́・ω・`)
Python処理系も外部に? 
• 例: Python 2 v.s. Python 3
Linux 
Re:VIEW 
Re:VIEW 
Re:VIEW 
Python 2.7 
Python 3.4 
Python 3.5 
(願望です)
今後について
今後のGriflet 
• 未だ「粛々と開発」 
• 「一般公開」出来る水準にしたい 
• 一部オープンソース化 
• https://github.com/dmiyakawa/pyrev 
• Re:VIEWのメタデータ解析 + Lintチェッカ
ありがとうございました 
この後オフィスアワーにいます
This page is 
intentionally left blank
……
まだまだ続くんじゃ 
(`・ω・́) 
発表で使わなかったスライドが延々続きます
「片手間」開発 
≒ 趣味
問題を愉しむ
運用環境の裏でテストしたい 
• 新しい原稿データでその場で「A/B テスト」 
• ここはあくまで今後の「希望」
Re:VIEW 
Linux
Re:VIEW 
Linux 
(WSGI)
Linux 
(WSGI) 
Re:VIEW
Linux 
Re:VIEW 
Re:VIEW 
Re:VIEW
Linux 
Re:VIEW 
Re:VIEW 
Re:VIEW 
Python 2.7 
Python 3.4 
Python 3.5
Linux 
Re:VIEW 
Re:VIEW 
Re:VIEW 
Python 2.7 
Python 3.4 
Python 3.5
あくまでアイディア
楽か?(́・ω・`)
バージョン管理の苦悩 
• 分離した部分でのセキュリティは自分で責任を持つ 
• 他人 (OSディストリビューション等) に 
どこまで頼って、どこから自分でやるのか? 
• 全環境を expose するわけではないので…… 
• ただ、考えておく必要はある
新しい何か 
≒ 新しい問題 
≒新しい発見 
• 「検証 ~= 実装」 
• 公開サービスではないので落ちてても切れる赤の 
他人がいない (今回助かるポイント) 
• 簡単な部分で敢えて一歩踏み出す 
• 経験値目当て 
• ただし、ヤバそうな点は忘れないようにメモする
ライブラリなのか 
それより下なのか 
• 多様な条件を切り替えられると気分が楽 
• CentOSに乗っける?問題ないだろ(`・ω・́) 
• ……systemdコワイ(́・ω・`) 
• OS固有の問題、Python環境の問題、ライブラリの 
問題、外部サービスの問題 
• 切り分けられるポイントで切り替える練習
実際、環境の一本化に 
やや難を感じている 
• 個人の事情もあるものの 
• 開発マシン: Debian 7 (wheezy) 
• 個人サーバ: Debian 7 (wheezy) 
• テスト環境: Ubuntu 12.04 LTS / Ubuntu 14.04 LTS 
• 「これも経験」と割り切る 
• (仕事の運用環境は一本化するのがベター) 
• BSDマダー
違うLinux 
細かいところでズレる 
! 
• Ubuntu 12.04 -> django 1.3 
• 使っていた reverse_lazy() がない 
• Pythonから上のレベルではせめて統一……
分離
virtualenv / venv 
• Python実行環境分離 
• 実行環境を(言語バージョン同じで)もう一つ作る 
• PyPiのパッケージも別管理 
• 最近 (3.3以降) なら(py)venv 
• 以降 venv = virtualenv or pyvenv 
• ……というか、どう呼ぶのがベストなの?
Django + venv の苦悩 
• activate忘れ (Apache, Celery含めて) 
• しかもある程度動作してしまうこともある…… 
• OS本体側にsudo pip全くしないのはどう? 
• あるいはmanage.pyの段階で強制?
Python環境も 
選びたくなる
Python環境も選びたい 
• virtualenvはPythonバージョン固定 
• make install すればいいのだが 
• 何かラフにでいいから管理したい
pyenv + venv 
• pyenv で任意のPython実行環境を(ユーザレベルで)用意 
• virtualenvのPython実行環境まるごと版みたいなの 
• https://github.com/yyuu/pyenv 
• rbenvのPython版なのでpyenv 
• 注意: pyenv ≠ pyvenv 
• venvを用いて、プロジェクト固有の環境をもう一つ作る 
• 3.系のpyvenvでは--copyを付けた方がベター
pyenv 実用例 
• Debian 7 のPython 2.7.3にマイナーなバグが…… 
• PyPiへのWindowsバイナリがアップ出来ない? 
• pyenvで2.7.6を入れることで回避出来た様子 
• 言語環境の軽いA/Bテストに使える
3種類のPython環境 
• システムレベル (OSパッケージ管理) 
• 保守的、OSに付属する環境が使う 
• ユーザレベル (pyenv) 
• 複数のPython環境をユーザが切り替える 
• OS付属のマイナーバージョンに不満がある場合にも便利 
• プロジェクトレベル (pyenv + venv) 
• プロジェクト毎にPython (+ PyPi) 環境を独立して持つ
mod_wsgiの苦悩 
• venvはApache + mod_wsgi のバージョンを 
強制できるわけではない 
• mod_wsgiのPythonバージョンはOS毎に異なる 
• 特に2と3の両立は不可 
• 他のWSGI依存のプロジェクトに影響する 
• 安易に変更はできない
WSGIを境界に
今試していること 
• pyenv + venv + Supervisor + tornado + 
Apache mod_proxy 
• どんどん複雑化していておじさん悲しいな
Supervisor 
• daemon管理のためのdaemon 
• Celeryを複数のDjangoプロジェクトで使いたいなら必須 
• 後述するtornadoの管理にも使う 
• OSによっては標準のバージョンが超古くアレなことが? 
• Debian 7 -> 2010年の頃のもの 
• 必要なら sid (unstable) からソースビルド
tornado 
• スタンドアローンWeb(WSGI)サーバ 
• http://www.tornadoweb.org/en/stable/ 
• Apacheのmod_wsgiを迂回するために使う。 
• Django 1.7 + tornadoでの注意 
• django.setup() 忘れるなや 
• 古い「tornado + Djangoを試してみた」系の記事内容だけだとハマる 
• http://qiita.com/amedama/items/a8f511bd75a14aac0277 
• 「異なるバージョンのPython(wsgi)アプリを一つの開発環境上で動かす」
素朴な疑問 
Supervisor v.s. systemd 
• 全く分からん(́・ω・`)
気軽に試せる環境が嬉しい 
• 「Python 3.X + Django 1.Y」をさっくり用意 
• /opt 下に一度に飼える 
• http://qiita.com/amedama/items/a8f511bd75a14aac0277 
• http://qiita.com/amedama/items/79994598d9f4daa69d13
楽しい!!! 
✌('ω'✌ )三✌('ω')✌三( ✌'ω')✌
ふたたび 
ありがとうございました
想定問答集
なぜmd/rst/etc.じゃない? 
• 極端な話、非常に抽象的なXMLを定義すれば 
なんでも書ける……はず。 
• それをしたくない適切な「軽量マークアップ」は何か 
• Re:VIEWは複数種類のアウトプット向け 
• 新しい文法的に拡張をし易い 
• 文法定義毎に固有の命令を埋め込みやすい 
• ただし「HTML出たけどPDFとInDesignが死んでる」が起こる 
• 日本の書籍事情に関与している方々が主導している 
• 参考: https://github.com/TechBooster/FirstStepReVIEW
Sphinx? 
• あ、ほら、最初良く知らなかったし(́・ω・`)
それ使ってみたい 
• Ask @amedama (Facebook dmiyakawa)
☆(ゝω・)vキャピ

More Related Content

"Continuous Publication" with Python: Another Approach