Jupyter 引入工作流

Jupyter 引入工作流

平时遇到一些场景需要使用代码演示的时候,一个个独立的py文件导致项目非常的混乱和松散。经过了Jupyter的极简入门之后,决定把它引入到自己的日常工作流。 用过才知有多香。

简介

正如百科中提到的,ipynb 的文件可以实现 python代码以及 markdown 的混合编写。以及可以对python 的代码进行分段的运行和调试。此外 pyplot之类图形化的lab 也可以直接在执行的结果中展示出来,十分的简单和方便。

Jupyter Notebook 的主要优势在于它的交互性和可重复性。它可以让用户轻松地探索数据、测试假设、创建模型并与他人共享自己的分析结果。此外,Jupyter Notebook 还提供了一些强大的可视化工具和数据处理库,使得数据科学家和研究人员可以更加高效地进行数据分析工作。

使用案例

写在前面

这里列出一个自己的使用真实案例,之后对自己用到的一些要点来进行总结。 这里只总结python 部分,markdown 部分和平时使用无太大差异。功能上支持了更多的公式表达。

这部分的代码非常的丑陋(冗余),是因为编写的时候就是奔着演示和单步执行去的。所以性能根本没有考虑。都是需要什么数据加什么数据,所以导致代码整体是不怎么优雅的

背景说明

因为有反馈是某个业务接口的请求存在异常的长耗时的情况,所以就使用了 curl 命令来请求并且输出请求的各项耗时。 一共14w条数据

curl -o /dev/null -s -w "time_namelookup: %{time_namelookup}\ntime_connect: %{time_connect}\ntime_appconnect: %{time_appconnect}\ntime_redirect: %{time_redirect}\ntime_pretransfer: %{time_pretransfer}\ntime_starttransfer: %{time_starttransfer}\ntime_total: %{time_total}\n" "https://api.xxx.xxx/perp/v1/order/cancel"
  • time_namelookup:从开始到域名解析完成时的耗时
  • time_connect:从开始到 TCP 连接建立完成的耗时
  • time_appconnect:从开始到 TLS 连接建立完成的耗时
  • time_redirect:多次重定向(如果有)的耗时
  • time_pretransfer:从开始到准备发送请求消息前的耗时
  • time_starttransfer:从开始到服务器准备返回第一个字节时的耗时
  • time_total:整个 HTTP 请求操作耗时

初始化部分

在notebook中代码是可以进行分段执行的,但是lib和 变量是共享的。所以在习惯上会把一些初始化的包引入单独出来。

!pip install matplotlib
!pip install numpy
import numpy
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from datetime import datetime 
import numpy as np
import re

魔法命令

这里值得注意的是这个 !开头的语句,这是JP中的魔法语句。 这里的意思是直接在shell中来执行pip安装所需要的包

  • !cmd是新建一个子shell执行cmd,cmd执行完了,这个子shell也就消失了。
  • 在当前shell生效,需要使用%cmd

参考

数据处理部分

数据读取以及值解析提取

import re

curve_data_map = {
    "time_namelookup": [],
    "time_connect": [],
    "time_appconnect": [],
    "time_redirect": [],
    "time_pretransfer": [],
    "time_starttransfer": [],
    "time_total": [],
    "x": []
}

with open('./curl.log') as f:
    line = f.readline()
    while line:
        ts = line.split('time_namelookup')[0].split()[0]
        pattern = r"\b-\d+\.\d+\b|\b-\d+\b\.\d+\b|-\d+\b|-\.\d+|\b\d+\.\d+\b|\b\d+\b\.\d+\b|\.\d+"
        elapseds = re.findall(pattern, line)
        curve_data_map['time_namelookup'].append(elapseds[0])
        curve_data_map['time_connect'].append(elapseds[1])
        curve_data_map['time_appconnect'].append(elapseds[2])
        curve_data_map['time_redirect'].append(elapseds[3])
        curve_data_map['time_pretransfer'].append(elapseds[4])
        curve_data_map['time_starttransfer'].append(elapseds[5])
        curve_data_map['time_total'].append(elapseds[6])
        curve_data_map['x'].append(ts)
        line = f.readline()

print(len(curve_data_map['time_total']), curve_data_map['time_total'][:10])

组成曲线数据

组装目前分析的曲线数据


def make_curve(serial_data):
    ser_avg_data = {
        'x':[],
        'y':[],
        'label': "Avg"
    }

    ser_p99_data = {
        'x':[],
        'y':[],
        'label': "p99"
    }
    ser_p95_data = {
        'x':[],
        'y':[],
        'label': "p95"
    }

    ser_p90_data = {
        'x':[],
        'y':[],
        'label': "p90"
    }


    def to_float(y):
        return [float(x) for x in y]

    elapsed_avg_padding = [sum(to_float(serial_data['y'])) / len(serial_data['y'])] * len(serial_data['y'])

    ser_avg_data['x']= serial_data['x']
    ser_p99_data['x'] = serial_data['x']
    ser_p95_data['x'] = serial_data['x']
    ser_p90_data['x'] = serial_data['x']

    ser_avg_data['y']= elapsed_avg_padding
    ser_p99_data['y'] = [np.percentile(to_float(serial_data['y']), 99)] * len(serial_data['y'])
    ser_p95_data['y'] = [np.percentile(to_float(serial_data['y']), 95)] * len(serial_data['y'])
    ser_p90_data['y'] = [np.percentile(to_float(serial_data['y']), 90)] * len(serial_data['y'])

    serial_data['label'] = "time"
    print(ser_avg_data['y'][0], ser_p99_data['y'][0], ser_p95_data['y'][0], ser_p90_data['y'][0])
    serials= [
        serial_data,
        ser_avg_data,
        ser_p99_data,
        ser_p95_data,
        ser_p90_data
    ]
    return serials

curve_map = {
    'time_namelookup': make_curve({"x":curve_data_map['x'], 'y': curve_data_map['time_namelookup']}),
    'time_connect': make_curve({"x":curve_data_map['x'], 'y': curve_data_map['time_connect']}),
    'time_appconnect': make_curve({"x":curve_data_map['x'], 'y': curve_data_map['time_appconnect']}),
    'time_redirect': make_curve({"x":curve_data_map['x'], 'y': curve_data_map['time_redirect']}),
    'time_pretransfer': make_curve({"x":curve_data_map['x'], 'y': curve_data_map['time_pretransfer']}),
    'time_starttransfer': make_curve({"x":curve_data_map['x'], 'y': curve_data_map['time_starttransfer']}),
    'time_total': make_curve({"x":curve_data_map['x'], 'y': curve_data_map['time_total']})
}

画图

# todo plot all serial in one polt with diffetent subplots
def plot_multi_line_svg(title, serials):
    def to_float(y):
        return [float(x) for x in y]
    def to_int(y):
        return [int(x) for x in y]
    fig, ax = plt.subplots()
    for serial in serials:
        try:
            dates = [datetime.fromtimestamp(ts) for ts in to_int(serial['x'])][10:10000]
            ax.plot(dates, to_float(serial['y'][10:10000]), label=serial['label'])
        except Exception as e:
            print(repr(e))
    # url decode title string
    import urllib.parse
    title = urllib.parse.unquote(title)
    # date_fmt = '%Y-%m-%d %H:%M:%S'
    date_fmt = '%H:%M'
    date_formatter = mdates.DateFormatter(date_fmt)
    ax.xaxis.set_major_formatter(date_formatter)
    ax.set_title(title)
    ax.legend()
    plt.ylabel("value")
    # today date YMD format
    plt.xlabel(datetime.now().strftime('%Y-%m-%d'))
    fig.autofmt_xdate()

    # image_name = "output.png"
    # fig.savefig(image_name, format='png', dpi=80)
    # return image_name

plot_multi_line_svg("time_namelookup", curve_map['time_namelookup'])
plot_multi_line_svg("time_connect", curve_map['time_connect'])
plot_multi_line_svg("time_appconnect", curve_map['time_appconnect'])
plot_multi_line_svg("time_redirect", curve_map['time_redirect'])
plot_multi_line_svg("time_pretransfer", curve_map['time_pretransfer'])
plot_multi_line_svg("time_starttransfer", curve_map['time_starttransfer'])
plot_multi_line_svg("time_total", curve_map['time_total'])

plt.show()

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注