はじめに¶
突然,「卒論でどのくらいコードを書いたんだろう?」と気になり,調べてみた.卒論で行ったデータ解析は,前処理,解析,可視化等をすべてPythonのnotebook(.ipynb)で書いている.そのため,作業用ディレクトリの中の全.ipynbファイルを調べて,コードの総行数をカウントすればよい.
以上より,本記事では,任意のディレクトリ配下の.ipynbファイルのコード総数を調べる方法を簡単にまとめる.
ipynbの仕様¶
ipynbファイルはjson記法のテキストファイルである.これをjupyter notebookやjupyterLabで開くことで,お馴染みの作業環境が実現する.
しかし,ipynbファイル自体はメタ情報も含まれた(json likeな)テキストファイルであるので,
そのファイル行数を確認しても自分で書いたpythonコードの行数にはならない.
実際に,テキストエディタ等でipynbファイルを開くと,json記法となっていることが確認できる.
例えば,このような作業環境に対応する部分は
以下のようなデータ形式で保存されている.
{'cells': [{'cell_type': 'code',
'execution_count': 4,
'metadata': {},
'outputs': [],
'source': ['import numpy as np\n',
'import pandas as pd\n',
'import json as json']},
{'cell_type': 'code',
'execution_count': 5,
'metadata': {},
'outputs': [],
'source': ["f = open('20190411_RC_base_link_table.json', encoding='utf-8-sig')\n",
'Link_dic = json.load(f)\n',
'f.close()\n',
'\n',
"f = open('20190516_RC_base_node_table.json', encoding='utf-8-sig')\n",
'Node_dic = json.load(f)\n',
'f.close()']},
{'cell_type': 'code',
'execution_count': 20,
'metadata': {},
'outputs': [{'data': {'text/plain': ["{'def_x_pos': 31,\n",
" 'def_y_pos': 15,\n",
" 'in_kanchiki_id_list': ['80-01-01', '00-01-08'],\n",
" 'in_link_list': ['498_505'],\n",
" 'node_attribute': 'O',\n",
" 'out_kanchiki_id_list': '0',\n",
" 'out_link_list': ['505_506']}"]},
'execution_count': 20,
'metadata': {},
'output_type': 'execute_result'}],
'source': ["Node_dic['505']"]},
.
.
.
}
詳細な仕様は,The Notebook file format — nbformat 4.5 documentation
にある.
今回は,セルごとのブロック中で,
source
キーに対応するアイテムが,実際に書いたpythonコードに該当することがわかれば良い.
リスト形式になっており,リストの各要素と行が対応している.
(markdown セルは,cell_type
が`markdown’となる.)
コード¶
# jsonデータをpythonの辞書で扱うために必要
import json
# ファイル操作に必要
import glob
# ひとつの.ipynbファイルのpythonコード行数をカウントする関数
def Count_Lines(file_path):
# ファイルを開き,辞書としてpythonの変数に流す
f = open(file_path, encoding='utf-8-sig')
ipynb_dict = json.load(f)
f.close()
Num_lines = 0
for cell_data in ipynb_dict['cells']:
# 各セルのpythonコード行数(=sourceリストの要素数)をカウント
if cell_data['cell_type'] == 'code':
Num_lines = Num_lines + len(cell_data['source'])
return Num_lines
# 動作の確認
file_path = '..\\20191108\\cheack.ipynb'
Count_Lines(file_path)
# XXXディレクトリ配下の.ipynbファイルのパスリストを取得
path = 'XXX//**//*.ipynb'
file_path_list = glob.glob(path, recursive=True)
# 全ファイルに対してpythonコード行数をカウント
data = {}
N = 0
for file_path in file_path_list:
Lines = Count_Lines(file_path)
data[file_path] = Lines
N = N + Lines
# 結果の確認
print('Number of files : ', len(file_path_list))
print('Number of lines : ', N)
おわりに¶
上記の結果は,実際の卒論作業ディレクトリに対して実施している.
ということで,1万8千行ほど書いたらしい.思ったより,少なく残念であった.