《捕蛇者说》的主题围绕『编程、程序员、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%添加类型注释的,建议阅读源代码就能够很好理解ASGI的Web框架的实现原理。
- 优点在于,让我们了解 ASGI和WSGI的区别。比如说像WebSocket这种服务器会主动向客户端发送通知的实时网页,如果使用WSGI只能使用HTTP协议,这样就需要客户端主动去轮询来完成实时页面的刷新。但是使用Async(ASGI)的这种模式,服务器就会直接向客户端发送信息,可以节省很多资源。
- 还有就是,我们收到客户端的一个任务之后,直接返回给客户端之后在处理,就需要添加一个任务队列(celery、apscheduler)来处理这个事情,会让我们的框架更加负载。但是如果直接使用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.7和Python3.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.
- Poetry和- Pipenv类似,是一个- Python虚拟环境和依赖管理工具,另外它还提供了包管理功能,比如打包和发布。你可以把它看做是- Pipenv和- Flit这些工具的超集。它可以让你用- 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. 视频文章
视频文章: 关于播客中推荐的视频和文章的一个汇总
推荐视频
- Python’s super() considered super!- 介绍在 Python 中使用 super() 函数以及 MRO 相关的一些东西,并非很多人理解的其调用父类中的一个方法。
 
- Python 3: ten years later - PyCon 2018- 对于刚刚接触 Python 语音的同学来,补充的一节 Python 历史的课程。
 
- David Beazley - Python Concurrency From the Ground Up- 大神 PyCon 现场撸代码,来告诉你什么是串行/并行,什么是同步/异步,什么是阻塞/非阻塞。
 
- Curious Course on Coroutines and Concurrency- 还是 David Beazley 大神的早起 PyCon 视频,很硬核的现场教你如何使用 yiled 来实现协程。
 
- Edwin Jung - Mocking and Patching Pitfalls - PyCon 2019- 主要介绍的是,你在测试里面为什么要 Mock?怎么 Mock?Mock 和 Patch 的区别。
 
- Dustin Ingram - PEP 572: The Walrus Operator - PyCon 2019- 主要介绍的是,
 
推荐文章
- Hidden features of Python- 主要讲述的是关于 Python 不为人知的知识。
 
 
                     
                     
                        
                        