Skip to content
Permalink
Browse files

Goodbye Pipenv!

Rewrite related chapters to use venv/virutlenv+pip, ripped out Pipenv
  • Loading branch information
greyli committed Nov 30, 2019
1 parent 7c3e716 commit 28ffb243bd905ade6c774eb8b747348df09091df
Showing with 65 additions and 53 deletions.
  1. +35 −21 chapters/c1-ready.md
  2. +1 −1 chapters/c10-organize.md
  3. +12 −14 chapters/c11-deploy.md
  4. +3 −3 chapters/c2-hello.md
  5. +6 −6 chapters/c5-database.md
  6. +4 −4 chapters/c8-login.md
  7. +4 −4 chapters/c9-test.md
@@ -130,57 +130,73 @@ $ git remote add origin git@github.com:greyli/watchlist.git # 注意更换地
* 指定不同的依赖版本
* 方便记录和管理依赖
我们将使用 Pipenv 来创建和管理虚拟环境、以及在虚拟环境中安装和卸载依赖包。它集成了 pip 和 virtualenv,可以替代这两个工具的惯常用法。另外,它还集成了 Pipfile,它是新的依赖记录标准,使用 Pipfile 文件记录项目依赖,使用 Pipfile.lock 文件记录固定版本的依赖列表。这两个文件替代了手动通过 requirements.txt 文件记录依赖的方式
我们将使用 Python 3 内置的 venv 模块创建虚拟环境
我们首先使用 pip 安装 Pipenv,Windows 系统使用下面的命令
如果你使用 Python 2,则需要安装 virtualenv 作为替代
```bash
$ pip install pipenv
$ pip install virtualenv
```
Linux 和 macOS 使用下面的命令
```bash
$ sudo -H pip install pipenv
$ sudo pip install virtualenv
```
使用 Pipenv 创建虚拟环境非常简单,使用 `pipenv install` 命令即可为当前项目创建一个虚拟环境
然后使用下面的命令即可为当前项目创建一个虚拟环境
```bash
$ pipenv install
$ python -m venv env
```
这个命令执行的过程包含下面的行为
Python 2 用户使用
* 为当前目录创建一个 Python 解释器环境,安装 pip、setuptool、virtualenv 等工具库。
* 如果当前目录有 Pipfile 文件或 requirements.txt 文件,那么从中读取依赖列表并安装。
* 如果没有发现 Pipfile 文件,就自动创建。
```bash
$ virtualenv env
```
上述命令的最后一个参数是虚拟环境名称,你可以自由定义,比如 venv、env、.venv,或是 项目名-venv,这里使用了 env。
这会在当前目录创建一个包含 Python 解释器环境的虚拟环境文件夹,名称为 env。
创建虚拟环境后,我们可以使用下面的命令来激活虚拟环境,如下所示(执行 `deactivate` 可以退出虚拟环境):
```bash
$ env\Scripts\activate # Windows
```
```bash
$ . env/bin/activate # Linux 或 macOS
```
创建虚拟环境后,我们可以使用 `pipenv shell` 命令来激活虚拟环境,如下所示(执行 `exit` 可以退出虚拟环境)
这时命令提示符前会显示虚拟环境的名称,表示已经激活成功
```bash
$ pipenv shell
(env) $
```
**注意** 除了 `pipenv install` 命令和 Git 相关命令外,除非特别说明,本书后续的所有命令均需要在激活虚拟环境后执行。如果你不想每次都激活虚拟环境,可以在命令前添加 `pipenv run` 前缀,比如 `pipenv run pip list` 即表示在虚拟环境内执行 `pip list` 命令
**注意** 除了 Git 相关命令外,除非特别说明,本书后续的所有命令均需要在激活虚拟环境后执行。

**提示** 建议为 Pip 和 Pipenv 更新 PyPI 源,改为使用国内的 PyPI 镜像源以提高下载速度,具体见[这篇文章](https://zhuanlan.zhihu.com/p/57872888)。
**提示** 建议为 pip 更新 PyPI 源,改为使用国内的 PyPI 镜像源以提高下载速度,具体见[这篇文章](https://zhuanlan.zhihu.com/p/57872888)。

## 安装 Flask

无论是否已经激活虚拟环境,你都可以使用下面的命令来安装 Flask:
激活虚拟环境后,使用下面的命令来安装 Flask:

```bash
$ pipenv install flask
(env) $ pip install flask
```

这会把 Flask 以及相关的一些依赖包安装到对应的虚拟环境,同时 Pipenv 会自动更新依赖文件
这会把 Flask 以及相关的一些依赖包安装到对应的虚拟环境。

**提示** 如果你没有使用虚拟环境,记得将 Flask 更新到最新版本(`pip install -U flask`)。

## 本章小结

当你进行到这里,就意味这我们已经做好学习和开发Flask程序的全部准备了。使用 `git status` 命令可以查看当前仓库的文件变动状态:
当你进行到这里,就意味这我们已经做好学习和开发 Flask 程序的全部准备了。使用 `git status` 命令可以查看当前仓库的文件变动状态:

```bash
$ git status
@@ -202,6 +218,4 @@ $ git push -u origin master # 如果你没有把仓库托管到 GitHub,则跳

* 阅读 MDN 的 [《Web 入门教程》](https://developer.mozilla.org/zh-CN/docs/learn)(了解 HTML、CSS、JavaScript)。
* 阅读短教程[《Git 简明指南》](http://rogerdudler.github.io/git-guide/index.zh.html)。
* 阅读文章[《Pipenv:新一代Python项目环境与依赖管理工具》](https://zhuanlan.zhihu.com/p/37581807)或 [Pipenv 官方文档](https://pipenv.readthedocs.io/en/latest/)。
* 如果你打算开源你的程序,在项目根目录中添加一个 README.md (自述文件)和 LICENSE (授权声明)是很有必要的。详情可以访问 [Open Source Guides](https://opensource.guide/) 了解。
* 在安装 Pipenv 时,你也可以使用 `--user` 选项进行用户安装(即 `pip install --user pipenv`)。用户安装可以避免破坏全局的包,而且可以避免对不可信的包使用 sudo pip 导致的潜在安全问题。详情见 [Pipenv 文档安装章节](https://docs.pipenv.org/install/#installing-pipenv)。
@@ -138,7 +138,7 @@ from watchlist.commands import forge, initdb
因为要测试的目标改变,测试时的 `--source` 选项的值也要更新为包的名称 `watchlist`

```bash
$ coverage run --source=watchlist test_watchlist.py
(env) $ coverage run --source=watchlist test_watchlist.py
```

**提示** 你可以创建配置文件来预先定义 `--source` 选项,避免每次执行命令都给出这个选项,具体可以参考文档[配置文件章节](https://coverage.readthedocs.io/en/v4.5.x/config.html)。
@@ -6,6 +6,12 @@ Web 程序通常有两种部署方式:传统部署和云部署。传统部署

## 部署前的准备

首先,我们需要生成一个依赖列表,方便在部署环境里安装。使用下面的命令把当前依赖列表写到一个 requirements.txt 文件里:

```bash
(env) $ pip freeze > requirements.txt
```

对于某些配置,生产环境下需要使用不同的值。为了让配置更加灵活,我们把需要在生产环境下使用的配置改为优先从环境变量中读取,如果没有读取到,则使用默认值:

```python
@@ -101,7 +107,6 @@ $ git push
在命令行下输入下面的命令:

```bash
$ pip3 install --user pipenv # 安装 Pipenv
$ git clone https://github.com/greyli/watchlist # 注意替换 Git 仓库地址
$ cd watchlist # 切换进程序仓库
```
@@ -110,8 +115,6 @@ $ cd watchlist # 切换进程序仓库

注意替换 git clone 命令后的 Git 地址,将 `greyli` 替换为你的 GitHub 用户名,将 `watchlist` 替换为你的仓库名称。

**提示** 如果你使用 Python 2.7,那么需要使用 pip 来执行安装 Pipenv 的命令;打开 Python Shell 时使用 python 命令,而不是 python3。

**提示** 如果你在 GitHub 上的仓库类型为私有仓库,那么需要将 PythonAnywhere 服务器的 SSH 密钥添加到 GitHub 账户中,具体参考第 1 章“设置 SSH 密钥”小节。

下面我们在项目根目录创建 .env 文件,并写入生产环境下需要设置的两个环境变量。其中,密钥(`SECRET_KEY`)的值是随机字符串,我们可以使用 uuid 模块来生成:
@@ -139,10 +142,11 @@ DATABASE_FILE=data-prod.db
最后安装依赖并执行初始化操作:

```bash
$ pipenv install # 创建虚拟环境并安装依赖
$ pipenv shell # 激活虚拟环境
$ flask initdb # 初始化数据库
$ flask admin # 创建管理员账户
$ python3 -m venv env # 创建虚拟环境
$ . env/bin/activate # 激活虚拟环境
(env) $ pip install -r requirements.txt # 安装所有依赖
(env) $ flask initdb # 初始化数据库
(env) $ flask admin # 创建管理员账户
```

先不要关闭这个标签页,后面我们还要在这里执行一些命令。点击右上角的菜单按钮,并在浏览器的新标签页打开 Web 面板。
@@ -181,13 +185,7 @@ PythonAnywhere 会自动从这个文件里导入名称为 `application` 的程

![虚拟环境配置](images/11-9.png)

使用 Pipenv 时,你可以在项目根目录下使用下面的命令获取当前项目对应的虚拟环境文件夹路径(返回前面打开的命令行会话输入下面的命令):

```bash
$ pipenv --venv
```

复制输出的路径,点击 Virtualenv 部分的红色字体链接,填入并保存。
对应我们的项目就是 `/home/greyli/watchlist/env/`,注意替换其中的用户名、项目名称和虚拟环境名称部分。点击 Virtualenv 部分的红色字体链接,填入并保存。

### 静态文件

@@ -19,10 +19,10 @@ def hello():
return 'Welcome to My Watchlist!'
```

按照惯例,我们把程序保存为 app.py,确保当前目录是项目的根目录,然后在命令行窗口执行 `flask run` 命令启动程序(按下 Control + C 可以退出):
按照惯例,我们把程序保存为 app.py,确保当前目录是项目的根目录,并且激活了虚拟环境,然后在命令行窗口执行 `flask run` 命令启动程序(按下 Control + C 可以退出):

```bash
$ flask run
(env) $ flask run
* Serving Flask app "app.py"
* Environment: production
WARNING: Do not use the development server in a production environment.
@@ -92,7 +92,7 @@ Flask 通过读取这个环境变量值对应的模块寻找要运行的程序
为了不用每次打开新的终端会话都要设置环境变量,我们安装用来管理系统环境变量的 python-dotenv:

```bash
$ pipenv install python-dotenv
(env) $ pip install python-dotenv
```

当 python-dotenv 安装后,Flask 会从项目根目录的 .flaskenv 和 .env 文件读取环境变量并设置。我们分别使用文本编辑器创建这两个文件,或是使用更方便的 `touch` 命令创建:
@@ -8,10 +8,10 @@

Flask 有大量的第三方扩展,这些扩展可以简化和第三方库的集成工作。我们下面将使用一个叫做 [Flask-SQLAlchemy](http://flask-sqlalchemy.pocoo.org/2.3/) 的官方扩展来集成 SQLAlchemy。

首先使用 Pipenv 安装它
首先安装它

```bash
$ pipenv install flask-sqlalchemy
(env) $ pip install flask-sqlalchemy
```

大部分扩展都需要执行一个“初始化”操作。你需要导入扩展类,实例化并传入 Flask 程序实例:
@@ -115,7 +115,7 @@ class Movie(db.Model): # 表名将会是 movie
模型类创建后,还不能对数据库进行操作,因为我们还没有创建表和数据库文件。下面在 Python Shell 中创建了它们:

```python
$ flask shell
(env) $ flask shell
>>> from app import db
>>> db.create_all()
```
@@ -157,13 +157,13 @@ def initdb(drop):
默认情况下,函数名称就是命令的名字,现在执行 `flask initdb` 命令就可以创建数据库表:

```bash
$ flask initdb
(env) $ flask initdb
```

使用 `--drop` 选项可以删除表后重新创建:

```bash
$ flask initdb --drop
(env) $ flask initdb --drop
```

## 创建、读取、更新、删除
@@ -328,7 +328,7 @@ def forge():
现在执行 `flask forge` 命令就会把所有虚拟数据添加到数据库里:

```bash
$ flask forge
(env) $ flask forge
```

## 本章小结
@@ -42,7 +42,7 @@ class User(db.Model):
因为模型(表结构)发生变化,我们需要重新生成数据库(这会清空数据):

```bash
$ flask initdb --drop
(env) $ flask initdb --drop
```

## 生成管理员账户
@@ -77,7 +77,7 @@ def admin(username, password):
使用 `click.option()` 装饰器设置的两个选项分别用来接受输入用户名和密码。执行 `flask admin` 命令,输入用户名和密码后,即可创建管理员账户。如果执行这个命令时账户已存在,则更新相关信息:

```bash
$ flask admin
(env) $ flask admin
Username: greyli
Password: 123 # hide_input=True 会让密码输入隐藏
Repeat for confirmation: 123 # confirmation_prompt=True 会要求二次确认输入
@@ -87,10 +87,10 @@ Done.

## 使用 Flask-Login 实现用户认证

扩展 [Flask-Login](https://github.com/maxcountryman/flask-login) 提供了实现用户认证需要的各类功能函数,我们将使用它来实现程序的用户认证,首先使用 Pipenv 安装它
扩展 [Flask-Login](https://github.com/maxcountryman/flask-login) 提供了实现用户认证需要的各类功能函数,我们将使用它来实现程序的用户认证,首先来安装它

```bash
$ pipenv install flask-login
(env) $ pip install flask-login
```

这个扩展的初始化步骤稍微有些不同,除了实例化扩展类之外,我们还要实现一个“用户加载回调函数”,具体代码如下所示:
@@ -422,7 +422,7 @@ if __name__ == '__main__':
使用下面的命令执行测试:

```bash
$ python test_watchlist.py
(env) $ python test_watchlist.py
...............
----------------------------------------------------------------------
Ran 15 tests in 2.942s
@@ -434,16 +434,16 @@ OK

## 测试覆盖率

为了让让程序更加强壮,你可以添加更多、更完善的测试。那么,如何才能知道程序里有哪些代码还没有被测试?整体的测试覆盖率情况如何?我们可以使用 [Coverage.py](https://coverage.readthedocs.io/en/v4.5.x/) 来检查测试覆盖率,首先安装它(添加 `--dev` 参数将它作为开发依赖安装)
为了让程序更加强壮,你可以添加更多、更完善的测试。那么,如何才能知道程序里有哪些代码还没有被测试?整体的测试覆盖率情况如何?我们可以使用 [Coverage.py](https://coverage.readthedocs.io/en/v4.5.x/) 来检查测试覆盖率,首先安装它:

```bash
$ pipenv install coverage --dev
(env) $ pip install coverage
```

使用下面的命令执行测试并检查测试覆盖率:

```bash
$ coverage run --source=app test_watchlist.py
(env) $ coverage run --source=app test_watchlist.py
```

因为我们只需要检查程序脚本 app.py 的测试覆盖率,所以使用 `--source` 选项来指定要检查的模块或包。

0 comments on commit 28ffb24

Please sign in to comment.
You can’t perform that action at this time.