一日一技:为 Python 项目编写 Makefile

简介: 一日一技:为 Python 项目编写 Makefile

摄影:产品经理某种海鲜锅

本文翻译自Writing Makefiles for Python Projects[1]。原作者:Bastian Venthur.

作为 Makefiles的粉丝,我几乎在每一个业余项目里面都使用它们。并且我也主张在工作项目中使用。

对开源项目来说,Makefiles 让代码贡献者知道怎么构建、测试、部署项目。并且,如果你正确使用了 Makefiles,他们可以大大简化你的CI/CD 流程脚本。因为你只需要简单地调用对应的 make 命令就可以了。最重要的是,Makefiles 可以简化你的开发工作。

对 Python 项目来说,我总是使用虚拟环境,因此我使用了两个不同的 Makefiles 策略:

  1. 假设 make 命令是在虚拟环境里面执行的
  2. 通过 make 命令来封装虚拟环境的命令

假设 make 命令是在虚拟环境中执行的

我们来看一个非常简单的 Makefile 文件,这个文件可以让你实现构建、测试和发布 Python 项目:

all: lint test
.PHONY: test
test:
    pytest
.PHONY: lint
lint:
    flake8
.PHONY: release
release:
    python3 setup.py sdist bdist_wheel upload
clean:
    find . -type f -name *.pyc -delete
    find . -type d -name __pycache__ -delete

这几段代码写的非常直接,所有潜在贡献者立刻就知道你项目的入口在哪里了。

假设已经有一个虚拟环境了,那么你需要首先激活它,然后再运行 make 命令:

$ . venv/bin/activate
$ make test

当然,不方便的地方在于,你的每一个 shell 窗口都必须手动激活虚拟环境。所以当你使用 tmux  激活一个新的终端窗口或者把 vim 放到后台上去运行的时候,就很麻烦。

在 make 命令里面激活虚拟环境看起来是很难做到的,因为每一段代码甚至每一个命令都会在它自己的 shell 里面运行。但是我们稍后看一个办法绕过这个限制,比如说使用.ONESHELL标志,但这无法解决新开新的代码片段运行在新 shell 的问题。

在 make 命令里面封装虚拟环境的调用命令

第二个方法基本上解决了在 make 命令里面激活虚拟环境的问题。这个办法是从makefile.venv[2]里面学到的,我简化了一下:

# system python interpreter. used only to create virtual environment
PY = python3
VENV = venv
BIN=$(VENV)/bin
# make it work on windows too
ifeq ($(OS), Windows_NT)
    BIN=$(VENV)/Scripts
    PY=python
endif
all: lint test
$(VENV): requirements.txt requirements-dev.txt setup.py
    $(PY) -m venv $(VENV)
    $(BIN)/pip install --upgrade -r requirements.txt
    $(BIN)/pip install --upgrade -r requirements-dev.txt
    $(BIN)/pip install -e .
    touch $(VENV)
.PHONY: test
test: $(VENV)
    $(BIN)/pytest
.PHONY: lint
lint: $(VENV)
    $(BIN)/flake8
.PHONY: release
release: $(VENV)
    $(BIN)/python setup.py sdist bdist_wheel upload
clean:
    rm -rf $(VENV)
    find . -type f -name *.pyc -delete
    find . -type d -name __pycache__ -delete

仅从功能上看,这个 Makefile 跟刚才的差不多,但是代码看起来更复杂了。所以我们现在一行一行来看看它是怎么实现的。

如果虚拟环境已经激活,或者pytest, flake8这些包已经安装到了系统 Python 环境里面,那么我们直接调用他们就可以了。但是现在,在新的 Makefile 文件中,我们显式地使用虚拟环境中的绝对路径来调用他们。为了确保虚拟环境存在,每一段代码都依赖于$(VENV)这一项。这一项确保了当前有一个最新的虚拟环境可用。

这种方案有效,是因为当我们执行. venv/bin/activate的时候,本来虚拟环境就是把它自己的绝对路径放到了环境变量里面。因此每一次调用 Python 或者其他包的时候,都是使用虚拟环境中安装的。

虽然 Makefile 文件变得有点复杂了,但是我们要测试代码的时候,还是仅仅需要简单地执行一下命令:

$ make test

就可以了,我们不需要再去关心虚拟环境是不是已经安装了之类的问题。如果你不需要支持 Windows,甚至可以从 Makefile 里面移除Windows 相关的部分。这样一来,这个 Makefile 文件即使对于不怎么用的人来说也不难理解。

哪一种更好?

我觉得第二种方案更方便。虽然第一种方法我已经快乐地用了几年了,而第二种方法是最近才学到的。之前我确实没有注意到这种方法。但我注意到几乎所有使用 Makefile的 Python 项目都用的第一种方法,我也想知道为什么。

Kingname 点评

我在Python 项目和Golang 项目里面经常使用Makefile,其中,Python 项目我主要用来删除__pycache__,而 Golang 项目中,由于我使用的是 VSCode 来开发,它的 lint 有点问题,所以代码写完以后,我会使用 Makefile 来执行一段gofmt命令,把所有.go文件都格式化。

但 Makefile 有一个非常智障的地方——它里面的缩进必须使用制表符,不能使用空格。所以要写Makefile 的时候,我还必须用 vim 来写。因为我的 PyCharm 已经调成把所有制表符换成空格的设置了。而如果在 Makefile 的缩进里面混入了空格,它就会报错。

如果大家对 Makefile 有兴趣的话,我给大家写一篇从入门到精通的文章。有兴趣的同学请留言~

目录
相关文章
|
16小时前
|
Python
【python】在pycharm创建一个新的项目
【python】在pycharm创建一个新的项目
366 0
|
16小时前
|
机器学习/深度学习 数据采集 数据可视化
Python众筹项目结果预测:优化后的随机森林分类器可视化|数据代码分享
Python众筹项目结果预测:优化后的随机森林分类器可视化|数据代码分享
|
16小时前
|
机器学习/深度学习 算法 UED
【Python 机器学习专栏】A/B 测试在机器学习项目中的应用
【4月更文挑战第30天】A/B测试在数据驱动的机器学习项目中扮演关键角色,用于评估模型性能、算法改进和特征选择。通过定义目标、划分群组、实施处理、收集数据和分析结果,A/B测试能帮助优化模型和用户体验。Python提供工具如pandas和scipy.stats支持实验实施与分析。注意样本量、随机性、时间因素和多变量分析,确保测试有效性。A/B测试助力于持续改进机器学习项目,实现更好的成果。
|
16小时前
|
存储 文字识别 计算机视觉
【python版CV】- 银行卡号识别项目
【python版CV】- 银行卡号识别项目
516 0
|
16小时前
|
Python
Python小项目:利用tkinter开发测手速小游戏
这个小游戏使用Tkinter创建了一个简单的图形用户界面,用户点击“开始”按钮开始测试,然后点击“停止”按钮停止测试并显示反应时间。你可以根据需要进一步定制化游戏的界面和功能。
539 1
|
16小时前
|
缓存 运维 Linux
保姆级python项目离线部署服务器教程只需这一篇就够了(建议收藏)
这篇文章提供了详尽的Python项目在离线Linux(CentOS)服务器上的部署教程。作者首先介绍了环境背景,强调了无网络环境和使用有网络的CentOS虚拟机准备安装包的重要性。教程分为两部分:外网环境搭建和内网离线安装。在外网环境中,包括下载Python 3.9.0安装包、传输至服务器、安装依赖包,并使用pip3下载项目所需依赖。内网安装则涉及依赖包的复制和Python环境的同样步骤。最后,作者分享了运行项目的命令,并总结了离线安装的整个流程,提醒读者注意可能出现的问题。
保姆级python项目离线部署服务器教程只需这一篇就够了(建议收藏)
|
16小时前
|
机器学习/深度学习 数据可视化 算法框架/工具
Python小项目:利用U-net完成细胞图像分割
这个项目能够锻炼你的深度学习技能,同时也能在医学、生物等领域有实际应用。你可以参考相关的教程和资源,如 GitHub 上的 U-Net 项目,以获得更详细的指导。 买CN2云服务器,免备案服务器,高防服务器,就选蓝易云。百度搜索:蓝易云
16 3
|
16小时前
|
Ubuntu 关系型数据库 MySQL
ubuntu部署python环境,vscode编辑wsl项目遇到的问题汇总
ubuntu部署python环境,vscode编辑wsl项目遇到的问题汇总
|
16小时前
|
前端开发 JavaScript 数据管理
描述一个使用Python开发Web应用程序的实际项目经验,包括所使用的框架和技术栈。
使用Flask开发Web应用,结合SQLite、Flask-SQLAlchemy进行数据管理,HTML/CSS/JS(Bootstrap和jQuery)构建前端。通过Flask路由处理用户请求,模块化代码提高可维护性。unittest进行测试,开发阶段用内置服务器,生产环境可选WSGI服务器或容器化部署。实现了用户注册登录和数据管理功能,展示Python Web开发的灵活性和效率。
16 4
|
16小时前
|
Linux 数据库连接 数据库
Python如何将项目直接打包为一键整合包
Python如何将项目直接打包为一键整合包
55 0