|
| 1 | +原文:[Makefiles in python projects —— Do you need such thing as makefile in python projects?](http://krzysztofzuraw.com/blog/2016/makefiles-in-python-projects.html) |
| 2 | + |
| 3 | +--- |
| 4 | + |
| 5 | +**当我加入我当前的公司时,我在他们的git仓库中看到了奇怪的文件。没有任何Python代码使用它。它仅仅是存在于项目的主目录下。我问我的同事,这个文件是用来干嘛的?他们告诉我——它让你的生活更轻松。这就是为什么今天我要写写这个文件 - Makefile。** |
| 6 | + |
| 7 | +目录: |
| 8 | + |
| 9 | + * makefile是什么,以及它的典型用途 |
| 10 | + * 具体到Python,你可以把什么放到makefile中 |
| 11 | + * 通过在Python项目中使用makefile,你可以获得什么好处 |
| 12 | + |
| 13 | +## makefile是什么,以及它的典型用途 |
| 14 | + |
| 15 | +根据这个[教程](http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/): |
| 16 | + |
| 17 | +> makefile是组织代码编译的一种简单方法。 |
| 18 | +
|
| 19 | +通常情况下,它们用于编写C程序,来减轻代码可以作为程序使用前所需要做的所有东西。你可以指定规则,告诉[make](https://www.gnu.org/software/make/)如何编译你的程序。用于C代码的简单的makefile如下: |
| 20 | + |
| 21 | +```shell |
| 22 | + helloword: helloword.c |
| 23 | + gcc -o hellword hellword.c -I. |
| 24 | + |
| 25 | +``` |
| 26 | + |
| 27 | +然后运行: |
| 28 | + |
| 29 | +```shell |
| 30 | + |
| 31 | + $ make helloword |
| 32 | + |
| 33 | +``` |
| 34 | + |
| 35 | +用gcc来编译C。 |
| 36 | + |
| 37 | +这怎么跟Python扯在一起了?Python这门编程语言在调用的时候才编译,因此不需要任何makefile。正如我在开头所说的,在Python项目中,使用makefile,你可以让你的生活变得轻松,并且节省大量的按键操作。 |
| 38 | + |
| 39 | +## 具体到Python,你可以把什么放到makefile中 |
| 40 | + |
| 41 | +构建Python包后,你有没有想过清理你项目中的`.pyc`文件,或者消除伪迹?或者也许你想要运行覆盖率测试?使用pep8, lint或者isort?或许在docker容器中运行应用,最终写出那些对你的屏幕来说太长的命令? |
| 42 | + |
| 43 | +这就是makefile的用武之地了。你可以将一切放在同一个地方,然后只使用`make clean`来清理不必要的文件,或者使用`make tests`来测试你的应用。 |
| 44 | + |
| 45 | +让我们先从我正在使用的makefile的一些例子开始: |
| 46 | + |
| 47 | +```python |
| 48 | + |
| 49 | + HOST=127.0.0.1 |
| 50 | + TEST_PATH=./ |
| 51 | + |
| 52 | + clean-pyc: |
| 53 | + find . -name '*.pyc' -exec rm --force {} + |
| 54 | + find . -name '*.pyo' -exec rm --force {} + |
| 55 | + find . -name '*~' -exec rm --force {} + |
| 56 | + |
| 57 | + clean-build: |
| 58 | + rm --force --recursive build/ |
| 59 | + rm --force --recursive dist/ |
| 60 | + rm --force --recursive *.egg-info |
| 61 | + |
| 62 | + isort: |
| 63 | + sh -c "isort --skip-glob=.tox --recursive . " |
| 64 | + |
| 65 | + lint: |
| 66 | + flake8 --exclude=.tox |
| 67 | + |
| 68 | + test: clean-pyc |
| 69 | + py.test --verbose --color=yes $(TEST_PATH) |
| 70 | + |
| 71 | + run: |
| 72 | + python manage.py runserver |
| 73 | + |
| 74 | + docker-run: |
| 75 | + docker build \ |
| 76 | + --file=./Dockerfile \ |
| 77 | + --tag=my_project ./ |
| 78 | + docker run \ |
| 79 | + --detach=false \ |
| 80 | + --name=my_project \ |
| 81 | + --publish=$(HOST):8080 \ |
| 82 | + my_project |
| 83 | + |
| 84 | +``` |
| 85 | + |
| 86 | +开头,我为每一个命令添加了两个变量`HOST`和`TEST_PATH`,以便使用它们。规则`clean-pyc`查找所有以`*.pyc`, `*.pyo`或者`*~`结尾的文件,然后删除它们。命令尾部的+号是用于`-exec |
| 87 | +command {}`,意味着命令的调用总数会比匹配的文件的数量要少得多。 |
| 88 | + |
| 89 | +下一个`clean-build`是用来提出构建伪迹。在`isort`中,shell根据何时的属性执行isort命令,`-c`标记用来从字符串而不是从标准输入读取命令。`lint`和`run`工作在相同的模式上。在`test`中,我添加了在实际的测试之前执行的额外的规则 - `clean-pyc`。最后的`docker-run`构建和运行docker。 |
| 90 | + |
| 91 | +你想要添加的额外的东西是一些称为`PHONY`的东西。默认情况下,makefile在文件上进行操作,因此,如果有个名为`clean- |
| 92 | +pyc`的文件,那么它会尝试使用它而不是使用命令。要避免这个,则在你的makefile文件开头使用`PHONY`: |
| 93 | + |
| 94 | +```python |
| 95 | + |
| 96 | + .PHONY: clean-pyc clean-build |
| 97 | + |
| 98 | +``` |
| 99 | + |
| 100 | +我还喜欢让我的makefile有帮助函数,因此我把这些放在里面的某些地方: |
| 101 | + |
| 102 | +```python |
| 103 | + |
| 104 | + help: |
| 105 | + @echo " clean-pyc" |
| 106 | + @echo " Remove python artifacts." |
| 107 | + @echo " clean-build" |
| 108 | + @echo " Remove build artifacts." |
| 109 | + @echo " isort" |
| 110 | + @echo " Sort import statements." |
| 111 | + @echo " lint" |
| 112 | + @echo " Check style with flake8." |
| 113 | + @echo " test" |
| 114 | + @echo " Run py.test" |
| 115 | + @echo ' run' |
| 116 | + @echo ' Run the `my_project` service on your local machine.' |
| 117 | + @echo ' docker-run' |
| 118 | + @echo ' Build and run the `my_project` service in a Docker container.' |
| 119 | + |
| 120 | +``` |
| 121 | + |
| 122 | +每个`echo`之前都有一个`@`,因为默认情况下,`make`载执行前把每一行都打印到控制台。`At`符号抑制这种行为,而当传递行给shell之前,`@`被丢弃。 |
| 123 | + |
| 124 | +但是,如果我想使用makefile,让我的应用程序运行在不同的主机和端口上呢?很简单,只需添加: |
| 125 | + |
| 126 | +```python |
| 127 | + |
| 128 | + run: |
| 129 | + python manage.py runserver --host $(HOST) --port $(PORT) |
| 130 | + |
| 131 | +``` |
| 132 | + |
| 133 | +接着,你可以简单地运行: |
| 134 | + |
| 135 | +```python |
| 136 | + |
| 137 | + $ make run HOST=127.0.0.1 PORT=8000 |
| 138 | + |
| 139 | +``` |
| 140 | + |
| 141 | +最后注意,makefile中的缩进必须使用TAB来完成,而不是空格。 |
| 142 | + |
| 143 | +## 通过在Python项目中使用makefile,你可以获得什么好处 |
| 144 | + |
| 145 | +正如你所见,在Python项目中使用makefile可以带来很多好东西。如果你已经厌倦了编写复杂的shell命令 —— 那么把它们放在makefile中的一个规则下。想要其他人很容易地运行对项目的测试吗?把pytest调用放在makefile中。创意是无止境的。 |
| 146 | + |
| 147 | +在你的项目中使用makefile吗?你觉得它有用,或者没用吗?你把什么其他的东西放在项目中呢?请把它写到评论中吧! |
| 148 | + |
0 commit comments