Weitere ähnliche Inhalte Ähnlich wie 使い捨て python コードの書き方 (20) 使い捨て python コードの書き方2. お前誰よ?
• Sho
Shimauchi
(
@shiumachi
)
• Cloudera
の問い合わせ担当
• 技術質問から人生相談まで幅広く対応
3. サポートに必要なもの
• Linux
コマンド
– sed,
awk,
grep,
find,
sort
…
– これで対応できるなら問題なし
• シェルスクリプト
– for
i
in
`ls`
と
for
i
in
`seq
N`
があればなんとかなる
• 正規表現
– 最強
– 最強と使いやすいかどうかは別問題
• 軽量言語
– 上記3つで簡単に対応できない場合はこれを使う
– 特に集計処理とか入ると正規表現ブン回すより簡単だし
再利用しやすい
4. ユースケース
• ほとんどがパース・集計処理
– ログ内の特定の文字をカウントする
– シーケンスIDをピックアップし、ギャップを検出、カ
ウントする
– 特定のIDを時系列で追跡し、クラスタ内での移動
経路を追う
• その一回だけでしか使わないことが大半なの
で、使い捨てのコードを書くことが多い
6. 使い捨て方(1)
適当なディレクトリに適当に書く
• 論外
• まず再利用不可能
– 場所がわからん
– 何に使ったかわからん
7. 使い捨て方(2)
git
で綺麗に管理する
• 理想的だが案外面倒
• どのコードも目的が違うので、ドキュメントの
整理・構造化も必要
• 同一名で投げ込むことができず、名前空間の
管理も必要
10. xUnit/TDD
の(個人的な)弊害
• xUnit
– クラス必須みたいに見えること
– 使い捨てコードでクラス必須って考えるだけでだるく
なる(個人的に)
• TDD
– 入門書を読むと 100%
原則を守らないといけないよう
に感じる
11. nose
• 色々便利な特徴はあるが、使い捨てコードに
おける大きな特徴は2つ
• テストクラス作成が不要
– test_*.py
としておいて、def
test_*:
というメソッド
を書いておけば nosetests
で自動実行できる
• nose.tools
– eq_(a,
b)
だけでほぼ全てまかなえる
14. エキPy
11
章より
テストのメリットは4つ
1. ソフトウェアのリグレッションの防止
2. コード、の品質の向上
3. 最適で低レベルなドキュメントの提供
4. よりすばやく、信頼性の高いコードの生産
15. エキPy
11
章より
テストのメリットは4つ
1. ソフトウェアのリグレッションの防止
2. コード、の品質の向上
3. 最適で低レベルなドキュメントの提供
4. よりすばやく、信頼性の高いコードの生産
使い捨てコードにおいては3,4
だけで十分
18. 実際の入力データ
hadoop
のネームノード(マスタ)のログ
2012-‐06-‐04
13:30:59,197
INFO
org.apache.hadoop.hdfs.server.namenode.NameNode:
STARTUP_MSG:
/************************************************************
STARTUP_MSG:
Starcng
NameNode
STARTUP_MSG:
host
=
sho-‐mba.local/192.168.100.130
STARTUP_MSG:
args
=
[]
STARTUP_MSG:
version
=
0.20.2-‐cdh3u4
STARTUP_MSG:
build
=
git://ubuntu-‐slave01/var/lib/jenkins/workspace/CDH3u4-‐Full-‐RC/build/cdh3/
hadoop20/0.20.2-‐cdh3u4/source
-‐r
214dd731e3bdb687cb55988d3f47dd9e248c5690;
compiled
by
'jenkins'
on
Mon
May
7
13:01:39
PDT
2012
************************************************************/
2012-‐06-‐04
13:30:59,680
INFO
org.apache.hadoop.metrics.jvm.JvmMetrics:
Inicalizing
JVM
Metrics
with
processName=NameNode,
sessionId=null
2012-‐06-‐04
13:30:59,683
INFO
org.apache.hadoop.hdfs.server.namenode.metrics.NameNodeMetrics:
Inicalizing
NameNodeMeterics
using
context
object:org.apache.hadoop.metrics.spi.NullContext
2012-‐06-‐04
13:30:59,788
INFO
org.apache.hadoop.hdfs.ucl.GSet:
VM
type
=
64-‐bit
2012-‐06-‐04
13:30:59,788
INFO
org.apache.hadoop.hdfs.ucl.GSet:
2%
max
memory
=
19.9175
MB
2012-‐06-‐04
13:30:59,788
INFO
org.apache.hadoop.hdfs.ucl.GSet:
capacity
=
2^21
=
2097152
entries
2012-‐06-‐04
13:30:59,789
INFO
org.apache.hadoop.hdfs.ucl.GSet:
recommended=2097152,
actual=2097152
2012-‐06-‐04
13:30:59,940
INFO
org.apache.hadoop.hdfs.server.namenode.FSNamesystem:
fsOwner=sho
(auth:SIMPLE)
2012-‐06-‐04
13:30:59,940
INFO
org.apache.hadoop.hdfs.server.namenode.FSNamesystem:
supergroup=supergroup
2012-‐06-‐04
13:30:59,940
INFO
org.apache.hadoop.hdfs.server.namenode.FSNamesystem:
isPermissionEnabled=true
2012-‐06-‐04
13:30:59,953
INFO
org.apache.hadoop.hdfs.server.namenode.FSNamesystem:
dfs.block.invalidate.limit=1000
20. テストコード
def test_parse():!
input = "2012-06-04 13:31:07,065 INFO
org.apache.hadoop.net.NetworkTopology: Adding a new node: /
default-rack/127.0.0.1:50010"!
input2 = "2012-06-04 13:31:05,466 WARN
org.apache.hadoop.util.PluginDispatcher: Unable to load
dfs.namenode.plugins plugins"!
expected = 'INFO'!
expected2 = 'WARN’!
eq_(expected, parse(input))!
eq_(expected2, parse(input2))!
入力データをベタ貼り
22. テストは通るが実際には動かない
2012-06-04 13:30:59,197 INFO org.apache.hadoop.hdfs.server.namenode.NameNode:
STARTUP_MSG: "
/************************************************************"
Traceback (most recent call last):"
File "nn_parse.py", line 23, in <module>"
main(sys.stdin)"
File "nn_parse.py", line 11, in main"
log_level = parse(line)"
File "nn_parse.py", line 5, in parse"
log_level = arr[2]"
IndexError: list index out of range
23. 失敗した行をそのままテストに追加
def test_parse():!
input = "2012-06-04 13:31:07,065 INFO
org.apache.hadoop.net.NetworkTopology: Adding a new node: /
default-rack/127.0.0.1:50010"!
input2 = "2012-06-04 13:31:05,466 WARN
org.apache.hadoop.util.PluginDispatcher: Unable to load
dfs.namenode.plugins plugins"!
input3 = "/
************************************************************"!
expected = 'INFO'!
expected2 = 'WARN'!
expected3 = '_NULL'!
eq_(expected, parse(input))!
eq_(expected2, parse(input2))!
eq_(expected3, parse(input3))
24. 失敗した行をそのままテストに追加
def test_parse():!
input = "2012-06-04 13:31:07,065 INFO
org.apache.hadoop.net.NetworkTopology: Adding a new node: /
default-rack/127.0.0.1:50010"!
input2 = "2012-06-04 13:31:05,466 WARN
org.apache.hadoop.util.PluginDispatcher: Unable to load
dfs.namenode.plugins plugins"!
input3 = "/
************************************************************"!
expected = 'INFO'!
expected2 = 'WARN'!
expected3 = '_NULL'!
eq_(expected, parse(input))!
eq_(expected2, parse(input2))!
eq_(expected3, parse(input3))