《捕蛇者说》摘录


《捕蛇者说》的主题围绕『编程、程序员、Python』展开

《捕蛇者说》摘录


1. Manjusaka

Manjusaka: Stay simple && Stay Naive

1.1 apscheduler - 定时任务

Task scheduling library for Python

  • 可以方便的帮助你在程序中做一些 Crontab 类的定时任务,并且自带了一些持久化和简单的分布式的功能,方便我们使用在小型项目。相对于重量级的 Celery 使用第三方的中间件作为 Broker 的,apscheduler 可以直接使用 Memory 进行任务存储。
  • 需要注意的是,如果使用 apscheduler 在多台服务器之前保持一个任务的同步性,就需要借助于第三方的工具,比如使用 Redis 等。
from pytz import utc

from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
from apscheduler.executors.pool import ProcessPoolExecutor


jobstores = {
    'mongo': {'type': 'mongodb'},
    'default': SQLAlchemyJobStore(url='sqlite:///jobs.sqlite')
}
executors = {
    'default': {'type': 'threadpool', 'max_workers': 20},
    'processpool': ProcessPoolExecutor(max_workers=5)
}
job_defaults = {
    'coalesce': False,
    'max_instances': 3
}
scheduler = BackgroundScheduler()

# .. do something else here, maybe add jobs etc.

scheduler.configure(jobstores=jobstores, executors=executors, job_defaults=job_defaults, timezone=utc)

1.2 pyrasite - 调试功能

Inject code into running Python processes

  • pyrasite 是一款基于 Python 的工具,利用 ptrace 来实现调试功能的,能够注入代码到 Python 进程中。如果系统是 MaxOS 的话,需要 gdb 版本大于 7.3 才可以使用。同时该工具还提供了 gui 的版本,但是需要额外安装。今天看了下,发现 gui 的版本很多年都没有人维护了,基本可以看作是废弃了,而且现在的版本已经不支持 Python3 了。
  • 该工具包含三个命令,分别是 pyrasite 查看 CPU 使用情况,pyrasite-shell 进入进程的 shell 中进行调试,pyrasite-memory-viewer 查看当前进程的最大对象。但是,好像所有的命令都只支持 Python2,真的不推荐各位用了,废材!
# 将任意代码注入正在运行的Python进程
$ pyrasite <PID> pyrasite/payloads/reverse_shell.py

# 进入指定的进程中进行调试
$ pyrasite-shell pid

# 使用命令查看当前进程的最大对象
$ pyrasite-memory-viewer pid

# 需要让内核支持进程调试(动态)
$ echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope

2. Laike9m

laike9m: I do a lot of different things

2.1 huey - 定时任务

a little task queue for python

  • 这个三方库就是一个非常轻量级的消息队列,实现了几乎所有 MQ 中应该有的功能。比如说,多进程、多线程和协程的支持,定时执行任务。纯 Python 实现的而且不依赖于任何三方库,官方推荐使用 Redis 作为 Broker 来一起使用。
from huey import RedisHuey, crontab

huey = RedisHuey('my-app', host='redis.myapp.com')

@huey.task()
def add_numbers(a, b):
    return a + b

@huey.task(retries=2, retry_delay=60)
def flaky_task(url):
    # This task might fail, in which case it will be retried up to 2 times
    # with a delay of 60s between retries.
    return this_might_fail(url)

@huey.periodic_task(crontab(minute='0', hour='3'))
def nightly_backup():
    sync_all_data()

2.2 Py-Spy - 性能分析

Sampling profiler for Python programs

  • 一个 Python 进程 CPU 取样分析工具,允许在不重启和修改源代码的情况下,可视化正在运行的 Python 程序的调用栈、时间消耗等,这对于分析生产环境程序是非常关键的。该工具包含三个子命令,分别是 top 表示命令行查看,dump 将堆栈信息保存下来,flame 输出成火焰图。
  • Py-spy 通过使用 Linux 上的 process_vm_readv 系统调用,OSX 上的 vm_read 调用或 Windows 上的 ReadProcessMemory 调用直接读取 Python 程序的内存样本数据分析。
# top
$ py-spy top --pid 12345
$ py-spy top -- python myprogram.py

# dump
$ py-spy dump --pid 12345

# record
$ py-spy record -o profile.svg --pid 12345
$ py-spy record -o profile.svg -- python myprogram.py

# docker
--cap-add SYS_PTRACE

# docker-compose
your_service:
   cap_add:
     - SYS_PTRACE

# kubernetes
securityContext:
  capabilities:
    add:
    - SYS_PTRACE

2.3 freezegun - 时间模块

Let your Python tests travel through time

  • freezegun 是一个库,它允许你的 Python 测试通过模拟 datetime 模块来穿越时间。在我们写测试用例关于时间方面的话,非常方便使用。
from freezegun import freeze_time
import datetime
import unittest


@freeze_time("2012-01-14")
def test():
    assert datetime.datetime.now() == datetime.datetime(2012, 1, 14)

# Or a unittest TestCase - freezes for every test, from the start of setUpClass to the end of tearDownClass

@freeze_time("1955-11-12")
class MyTests(unittest.TestCase):
    def test_the_class(self):
        assert datetime.datetime.now() == datetime.datetime(1955, 11, 12)

# Or any other class - freezes around each callable (may not work in every case)

@freeze_time("2012-01-14")
class Tester(object):
    def test_the_class(self):
        assert datetime.datetime.now() == datetime.datetime(2012, 1, 14)

3. Laixintao

Laixintao: 我有一种特别的幽默感

3.1 starlette - 异步框架

The little ASGI framework that shines.

  • 该库是一个类似于 Flask(WSGI) 的 ASGI 的异步 Web 框架,代码量非常少而且 100% 测试覆盖和 100% 添加类型注释的,建议阅读源代码就能够很好理解 ASGIWeb 框架的实现原理。
  • 优点在于,让我们了解 ASGIWSGI 的区别。比如说像 WebSocket 这种服务器会主动向客户端发送通知的实时网页,如果使用 WSGI 只能使用 HTTP 协议,这样就需要客户端主动去轮询来完成实时页面的刷新。但是使用 Async(ASGI)的这种模式,服务器就会直接向客户端发送信息,可以节省很多资源。
  • 还有就是,我们收到客户端的一个任务之后,直接返回给客户端之后在处理,就需要添加一个任务队列(celeryapscheduler)来处理这个事情,会让我们的框架更加负载。但是如果直接使用 Async 的话,因为其本身就自带时间循环的机制,可以在时间循环中添加更多的任务,从而简化处理流程。但是需要注意的是,如果使用 starlette 这个库的话,你用到的所有的库都必须使用 AsyncIO 的,这个比较蛋疼。
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route


async def homepage(request):
    return JSONResponse({'hello': 'world'})

routes = [
    Route("/", endpoint=homepage)
]

app = Starlette(debug=True, routes=routes)

3.2 PySnooper - 输出优化

Never use print for debugging again

  • 一般情况下,想要知道哪一行代码在运行、哪一行不运行、本地变量的值是多少时,大部分人会使用 print 函数,在关键部分打印某个或某组变量的值、形状、类型等信息。
  • PySnooper 让你能快速地获得这些信息,且相比之下它不需要细致地写 print 函数,只需要向感兴趣的函数增加一个装饰器就行了。我们会得到该函数的详细 log,包含哪行代码能运行、什么时候运行以及本地变量变化的确切时间。
import pysnooper

@pysnooper.snoop()
def number_to_bits(number):
    if number:
        bits = []
        while number:
            number, remainder = divmod(number, 2)
            bits.insert(0, remainder)
        return bits
    else:
        return [0]

number_to_bits(6)

3.3 httmock - 单元测试(不更)

A mocking library for requests

  • Mock 这个词在英语中有模拟的这个意思,而用在程序中的话,就是用于支持单元测试生成伪造数据或请求的。所以在 Python 中,它就是一个用于支持单元测试的库,主要功能是使用 mock 对象替代掉指定的 Python 对象,从而达到模拟对象的行为进行测试。在 Python3.x 中标准库中已经自带了官方的 Mock 库。
  • httmock 就是生成伪造请求的第三方库,尤其在写爬虫测试的时候常常会使用到。它不像标准库中的 Mock 库,写测试用例的是时候需要写一坨代码,只需要简单的几行就用实现你需要的功能了。
from httmock import urlmatch, HTTMock
import requests

@urlmatch(netloc=r'(.*\.)?google\.com$')
def google_mock(url, request):
    return 'Feeling lucky, punk?'

with HTTMock(google_mock):
    r = requests.get('http://google.com/')
print r.content  # 'Feeling lucky, punk?'

3.4 pyinstrument - 堆栈分析(少更)

Call stack profiler for Python. Shows you why your code is slow!

  • 这个库也是一个用于分析 Python 堆栈的分析器,可以帮助我们查找到代码为什么慢的原因,从而优化代码性能。同时,该库支持 Python2.7Python3.3+ 的各个版本。需要注意的是,其也是一个入侵形式的分析工具。
# 一个简单的分析Flask应用程序的设置
from flask import Flask, g, make_response, request
app = Flask(__name__)

@app.before_request
def before_request():
    if "profile" in request.args:
        g.profiler = Profiler()
        g.profiler.start()

@app.after_request
def after_request(response):
    if not hasattr(g, "profiler"):
        return response
    g.profiler.stop()
    output_html = g.profiler.output_html()
    return make_response(output_html)

4. AdamWen

AdamWen: 一个在知乎工作的 Pythonista

4.1 pyflame - 内存分析(归档)

A Ptracing Profiler For Python.

  • 一个 Python 内存使用问题定位的工具,主要的优势是使用过程中对已有的代码没有侵入性,就类似于 py-spy 一样,只不过后者是定位 CPU 使用的情况。另外一点是,它对于 gevent(提供了比较完善的协程支持) 的支持非常友好。目前,该项目已经废弃了,基本使用不了,废材了。
# 安装依赖工具
$ sudo apt-get install autoconf automake autotools-dev g++ make
$ sudo apt-get install pkg-config python-dev python3-dev libtool

# 下载镜像包
$ git clone https://github.com/uber/pyflame.git
$ cd pyflame

# 编译二进制文件
$ ./autogen.sh
$ ./configure
$ make

# 简单使用
$ pyflame -p 12345
$ pyflame -s 5 -r 0.01 -p 768
$ pyflame -o prof.txt -t py.test tests/

# 生成火焰图
$ git clone https://github.com/brendangregg/FlameGraph.git
$ cd FlameGraph
$ pyflame -s 5 -r 0.01 -p 768 | flamegraph.pl > myprofile.svg

4.2 Click - 脚本工具

Python composable command line interface toolkit

  • Click 是一个利用很少的代码以可组合的方式创造优雅命令行工具接口的 Python 库。 它是高度可配置的,但却有合理默认值的“命令行接口创建工具”。它致力于将创建命令行工具的过程变的快速而有趣,免除你因无法实现一个 CLIAPI 的挫败感。
import click

@click.command()
@click.option("--count", default=1, help="Number of greetings.")
@click.option("--name", prompt="Your name", help="The person to greet.")
def hello(count, name):
    """Simple program that greets NAME for a total of COUNT times."""
    for _ in range(count):
        click.echo(f"Hello, {name}!")

if __name__ == '__main__':
    hello()

5. Escape

Escape: 我想给这个世界留下点什么!

5.1 line_profiler - 性能分析(归档)

Line-by-line profiling for Python

  • line_profiler 模块用来测试函数每行代码的响应时间等情况,该模块和 cProfile 不同,它不像 cProfile 那样只关注函数调用消耗的 CPU 时间,而是可以帮助你一行一行地分析函数性能。有时候,瓶颈问题发生在函数的某一行中,这时就需要 line_profiler 解决了。
from line_profiler import LineProfiler
import random

def do_stuff(numbers):
    s = sum(numbers)
    l = [numbers[i]/43 for i in range(len(numbers))]
    m = ['hello'+str(numbers[i]) for i in range(len(numbers))]

numbers = [random.randint(1,100) for i in range(1000)]
lp = LineProfiler()
lp_wrapper = lp(do_stuff)
lp_wrapper(numbers)
lp.print_stats()

5.2 memory_profiler - 内存分析

Monitor Memory usage of Python code

  • 该工具可以按每行代码查看内存的占用情况和监视进程的内存消耗,使用的时候依赖 psutil 模块,但使用起来非常简单。
@profile
def my_func():
    a = [1] * (10 ** 6)
    b = [2] * (2 * 10 ** 7)
    del b
    return a

if __name__ == '__main__':
    my_func()

5.3 Scalene - 性能分析

a high-performance, high-precision CPU, GPU, and memory profiler for Python

  • Scalene 是一个 Python 的高性能 CPU 和内存分析器,它可以做到很多其他 Python 分析器不能做到的事情。它在能提供更多详细信息的同时,比其他的分析器要快几个数量级。Scalene 可以成为调试程序的集大成者,支持 CPU 和内存行级别的执行使用情况,而且开销一般不超过 10-20%,通常情况下更少。
  • 和大部分其他的 Python 分析器不同,Scalene 在行级别下执行 CPU 分析,在你的程序中指出对应代码行的执行时间。和大多数分析器所返回的功能级分析结果相比,这种程度的细节可能会更有用。而且 Scalene 可以分析内存使用情况。除了追踪 CPU 使用情况外,Scalene 还指出对应代码行的内存增长,这是通过指定内存分配器来实现的。
  • 最新的版本中,Scalene 会生成每行的内存分析,以此更容易的追踪内存泄露。而且还会分析内存拷贝量, 从而易于发现意外的内存拷贝,特别是因为跨越 Python 和底层库的边界导致的意外。
# 默认的安装方式不提供内存分析能力
# 需要的话,则需要下载这个代码仓库(Max系统提供的对应工具)
$ pip install scalene

# 手动构建一个指定的内存分配器(Linux/MacOX)
$ LD_PRELOAD=$PWD/libscalene.so PYTHONMALLOC=malloc scalene test/testme.py
$ DYLD_INSERT_LIBRARIES=$PWD/libscalene.dylib PYTHONMALLOC=malloc scalene test/testme.py
# 执行行级别的CPU和内存分析(命令行)
$ scalene test/testme.py

# 执行行级别的CPU和内存分析(模块)
$ python -m scalene test/testme.py

5.4 poetry - 虚拟环境

Python dependency management and packaging made easy.

  • PoetryPipenv 类似,是一个 Python 虚拟环境和依赖管理工具,另外它还提供了包管理功能,比如打包和发布。你可以把它看做是 PipenvFlit 这些工具的超集。它可以让你用 Poetry 来同时管理 Python 库和 Python 程序,不过 Python 官方推荐的虚拟工具还是 Pipenv
  • 有人说,Pipenv 描绘了一个美梦,让我们以为 Python 也有了其他语言那样完善的包管理器,不过这一切却在后来者 Poetry 这里得到了更好的实现。
# 基本信息
[tool.poetry]
name = "poetry-demo"
version = "0.1.0"
description = ""
authors = ["Sébastien Eustace <[email protected]>"]

# 项目依赖
# 特殊依赖pendulum的版本^1.4表示(>=1.4.0 & <2.0.0)之间
[tool.poetry.dependencies]
python = "*"
pendulum = "^1.4"
my-package = {path = "../my/path", develop = false}

# 开发依赖
[tool.poetry.dev-dependencies]
pytest = "^3.4"

# 在项目的virtualenv内部执行给定命令
[tool.poetry.scripts]
my-script = "my_module:main"

5.5 Procmon - 进程监控(少更)

Process Monitor for Linux

  • Process Monitor 是一种进程监控工具,为开发者提供了简便有效的方式来跟踪系统调用(syscall)活动。该工具能够帮助诊断程序崩溃、资源占用率过高,甚至是潜在的恶意感染等问题。Sysinternals 工具集在 Windows 上堪称经典,功能强大。现在,Linux 用户也可以尝试使用 Procmon 来监控系统进程。
# 使用以下参数指定要监视的进程ID或特定的系统调用
Usage: procmon [OPTIONS]
   OPTIONS
      -h/--help                Prints this help screen
      -p/--pids                Comma separated list of process ids to monitor
      -e/--events              Comma separated list of system calls to monitor
      -c/--collect [FILEPATH]  Option to start Procmon in a headless mode
      -f/--file FILEPATH       Open a Procmon trace file

# 监视ID编号为738和2657进程
$ sudo procmon -p 738,2657

# 监视PID编号为738列出的所有读写调用
$ sudo procmon -p 738 -e read,write

5.6 memray - 内存分析

Memray is a memory profiler for Python

可视化分析 Python 内存占用的一个包,可以在单月测试的时候加上对应的 lint 检查,能够更好地分析出代码的瓶颈和质量问题。它可以生成几种不同类型的报告,以帮助您分析捕获的内存使用数据。虽然通常作为 CLI 工具使用,但它也可以作为库来执行更细粒度的分析任务。

如果希望在测试中使用 memray 工具的话,可以考虑使用 pytest-memray。安装之后,这个 pytest 插件允许你简单地添加 memray 到命令行调用中。

# 使用它作为命令行工具来运行脚本、应用程序或库
usage: memray [-h] [-v] {run,flamegraph,table,live,tree,parse,summary,stats} ...

Memory profiler for Python applications

Run `memray run` to generate a memory profile report, then use a reporter command
such as `memray flamegraph` or `memray table` to convert the results into HTML.

Example:

    $ python3 -m memray run my_script.py -o output.bin
    $ python3 -m memray flamegraph output.bin

positional arguments:
  {run,flamegraph,table,live,tree,parse,summary,stats}
                        Mode of operation
    run                 Run the specified application and track memory usage
    flamegraph          Generate an HTML flame graph for peak memory usage.
    table               Generate an HTML table with all records in the peak memory usage.
    live                Remotely monitor allocations in a text-based interface.
    tree                Generate an tree view in the terminal for peak memory usage.
    parse               Debug a results file by parsing and printing each record in it.
    summary             Generate a terminal-based summary report of the functions that allocate most memory
    stats               Generate high level stats of the memory usage in the terminal

optional arguments:
  -h, --help            show this help message and exit
  -v, --verbose         Increase verbosity. Option is additive, can be specified up to 3 times.
# 在脚本或单个python文件中使用
$ python3 -m memray run my_script.py

# 使用模块运行你的应用程序
$ python3 -m memray run -m my_module

# 作为命令行工具调用
$ memray run my_script.py
$ memray run -m my_module

# 输出是一个二进制文件可以以不同的方式分析它
# 常见的一种方法是使用memray火焰图命令生成火焰图
$ memray flamegraph my_script.2369.bin

# 检查lint检测
$ pytest --memray tests/

# live模式
# 基于终端的界面中运行一个脚本或模块允许在运行时交互式地检查其内存使用情况
# 这对于调试运行时间较长的脚本或模块或显示出多种复杂内存模式的脚本或模块非常有用
$ memray run --live my_script.py
$ memray run --live -m my_module

5.7 python-fire - 脚本工具

Python Fire is a library for automatically generating command line interfaces (CLIs).

当我需要写一个或多个命令行脚本工具的时候,头脑中首先会想到使用 Python 标准库中自带的 argparse 模块来完成该任务。但是写完之后,会发现 argparse 又臭又长,很不美观。此时,就需要使用我们这里介绍的 fire 第三方库了。当使用了了之后,会发现其命令行变得非常简单,只需要两行代码就可以完成了。

import fire

def hello(name="World"):
    return "Hello %s!" % name

if __name__ == '__main__':
    fire.Fire(hello)

6. 视频文章

视频文章: 关于播客中推荐的视频和文章的一个汇总

推荐视频


推荐文章


文章作者: Escape
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Escape !
  目录