【lab】常规操作:log写法,运行和数据信息管理,测试管理,多线程/进程tips
第一个问题:
“你写log了没?”
第二个问题:
“你写log了没?”
第三个问题:
“你写log的时间到一个小时了没?没有的话再去写log”
log:
log密度: 大概每100行有10个 -- 因为平均每一百行code会产生10个左右潜在的关键节点(同时100行可能有6-8个bug点)。log多多益善,之前的努力是之后的欣慰。
从coding的角度讲,永远避免写暂时的code,包括绘图的code,处理数据的code,超过30行就要考虑打包并且写详细的文档。如果超过10个函数,考虑生成大文档。
熟练掌握所有工具语言的输入输出I/O函数。
每天可能产生上千行的log。为了避免混乱,所有当天的log都dump到一个或者多个只以日期命名的文件中。
请熟练运用各种命令行文档查找,编辑器regex查询,以及写Python脚本提取单个task的log片段。
- log风格
Python:
临时:
print("a has been incremented 1. \n", file="log.txt")
集中管理:
from time import localtime, strftime
def log(msg="", mute=0):
print(msg, file="log_%s.txt" % strftime("%b%d_%H%M%S", localtime()))
# "%b%d_%H%M%S ": 'Mar20_150921'
- 模板
LOG FILE FOR DATE: 03/19/2019
==========================
time start: %s
task: %s
source code file: %s
output files:
==========================
time hh:MM:ss: (checkpoint)
(stdout, stderr)
time hh:MM:ss: (checkpoint)
(stdout, stderr)
...
==========================
time start: %s
task: %s
source code file: %s
output files:
==========================
time hh:MM:ss: (checkpoint)
(stdout, stderr)
定时开始
- bash
echo "python run.py" | at 4:00
atq # get job ids
at -d <job-id> # cancel job
数据信息(time stamp, entries, method, notes, etc)
任何分布式环境都适用的一个风格:每个文件保存自己的header,而不是用一个中央索引来整合和记录。
因此最有效的整合零散实验数据的方法,是在每一个的首行记录详细信息,并且标注好各个数据项。
测试
命名一律:test_
方便git提交的时候写入.gitignore
多进程/线程长时间运行
-
将需要运行的参数保存在一个外部文件,而不是临时写在代码里。(待实践)
-
如果对参数没有事先要求/偏好, e.g. 采取地毯式搜索最优参数,可以将参数乱序后分配给不同的进程/线程而不是顺序分配,这样任何时刻得到的数据都有一定代表性
-
保存参数运行信息,查看具体参数运行时间,估计总体运行时间。在运行函数中加入以下语句将参数的开始运行和结束时间输出到文件:
def run(): # the func to be run by each thread/process
with open("log.txt", "a+") as f:
f.write("params <params> begin at <time stamp sec>\n")
...
with open("log.txt", "a+") as f:
f.write("params <params> finish at <time stamp sec>\n")
然后对文件进行清理:
import re
import time
import sys
sys.stdout = open("log/running_log_clean%d.txt" % time.time())
# ['MK', 'batch_all', './log/%s2019_%sNetwork_%s_core%s.txt', (1, 0), 3, 1000, 2, 50, (0.1, 0.6), 0.02, 0.12000000000000001]
param_text = re.compile(r"\[.+\]")
param_dic = dict()
with open("log/running_log.txt", 'r') as f:
line = f.readline()
while line:
param_raw = re.findall(param_text, line)[0]
param_dic.setdefault(param_raw, dict())
if param_raw:
if re.findall(r"begin", line):
param_dic[param_raw]["start_time"] = re.findall(r'1553......', line)[0] # year 2019
elif re.findall(r"finish", line):
param_dic[param_raw]["end_time"] = re.findall(r'1553......', line)[0]
print("param %s finish in %d secs", param_raw, param_dic[param_raw]["end_time"] - param_dic[param_raw]["start_time"])
else:
print("param %s running for %d secs", param_raw, round(time.time()) - param_dic[param_raw]["start_time"])
line = f.readline()
- 如果是多进程运行,注意将stderr和stdout重定向到输出文件。因为程序运行之后各自在自己的进程中输出,不会打印到当前的shell中。方法如下 https://stackoverflow.com/questions/1501651/log-output-of-multiprocessing-process:
from multiprocessing import Process
import os
import sys
def info(title):
print title
print 'module name:', __name__
print 'parent process:', os.getppid()
print 'process id:', os.getpid()
def f(name):
sys.stdout = open(str(os.getpid()) + ".out", "w")
info('function f')
print 'hello', name
if __name__ == '__main__':
p = Process(target=f, args=('bob',))
p.start()
q = Process(target=f, args=('fred',))
q.start()
p.join()
q.join()
# output
'''
$ ls
m.py
$ python m.py
$ ls
27493.out 27494.out m.py
$ cat 27493.out
function f
module name: __main__
parent process: 27492
process id: 27493
hello bob
$ cat 27494.out
function f
module name: __main__
parent process: 27492
process id: 27494
hello fred
'''