对于Python新手来说,Python部署可能看起来并不简单。大量可选安装的库和包也是如此。首先,Python不止一种。Python有多种不同的风格,如CPython、Jython、IronPython和PyPy。还有Python 2.7与3.x世界之间的分歧。¹
即使你决定了版本,部署仍然因其他一些原因而变得困难:
• 解释器(标准CPython安装)仅附带所谓的标准库(例如涵盖典型数学函数) • 可选的Python包需要单独安装——而且有成百上千个 • 由于依赖关系和特定操作系统的要求,自行编译/构建这些非标准包可能很棘手 • 处理这些依赖关系和随时间保持版本一致性(即维护)通常是繁琐和耗时的 • 某些包的更新或升级可能需要重新编译许多其他包 • 更改或替换一个包可能导致(许多)其他地方的麻烦
幸运的是,有一些可用的工具和策略可以提供帮助。本章涵盖以下有助于Python部署的技术类型:
包管理器(Package managers) 像pip和conda这样的包管理器有助于安装、更新和移除Python包;它们还有助于保持不同包的版本一致性。
虚拟环境管理器(Virtual environment managers) 像virtualenv或conda这样的虚拟环境管理器允许你并行管理多个Python安装(例如,在单台机器上同时拥有Python 2.7和3.7安装,或测试某个新奇Python包的最新开发版本而无风险)。²
容器(Containers) Docker容器代表完整的文件系统,包含运行特定软件所需的所有系统组件,如代码、运行时或系统工具。例如,你可以在运行macOS或Windows 10的机器上托管的Docker容器中,运行带有Python 3.7安装和相应Python代码的Ubuntu 18.04操作系统。
云实例(Cloud instances) 部署用于金融应用的Python代码通常需要高可用性、安全性和性能;这些要求通常只能通过使用专业的计算和存储基础设施来满足,而如今这些基础设施以从相当小到真正大而强大的云实例的形式,以优惠的条件提供。与长期租用的专用服务器相比,云实例的一个好处是用户通常只按实际使用的小时数付费;另一个优势是,如果需要,这类云实例实际上在一两分钟内就可以启动,这有助于敏捷开发和可扩展性。
本章的结构如下:
conda作为包管理器 本节介绍conda作为Python包管理器的用法。
conda作为虚拟环境管理器 本节重点介绍conda作为虚拟环境管理器的能力。
使用Docker容器 本节简要概述Docker作为容器化技术,并重点介绍构建基于Ubuntu的、包含Python 3.7安装的容器。
使用云实例 本节展示如何在云端部署Python和Jupyter Notebook——一套强大的、基于浏览器的Python开发工具套件。
本章的目标是在专业基础设施上建立正确的Python安装,配备最重要的工具以及数值、数据分析和可视化包。这样的组合将作为后续章节中实现和部署Python代码的骨干——无论是交互式金融分析代码,还是脚本和模块形式的代码。
conda作为包管理器#
虽然conda可以独立安装,但一种高效的方式是通过Miniconda,它是一个最小的Python发行版,包含conda作为包和虚拟环境管理器。
安装Miniconda#
Miniconda适用于Windows、macOS和Linux。你可以从Miniconda网页下载不同版本。以下假设使用Python 3.7 64位版本。本节的主要示例是在基于Ubuntu的Docker容器中进行会话,通过wget下载Linux 64位安装程序,然后安装Miniconda。所展示的代码应该适用于任何其他基于Linux或macOS的机器(可能只需稍作修改):
$ docker run -ti -h py4fi -p 11111:11111 ubuntu:latest /bin/bash
root@py4fi:/# apt-get update; apt-get upgrade -y
...
root@py4fi:/# apt-get install -y bzip2 gcc wget
...
root@py4fi:/# cd root
root@py4fi:~# wget \
> https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh \
> -0 miniconda.sh
...
HTTP request sent, awaiting response... 200 OK
Length: 62574861 (60M) [application/x-sh]
Saving to: 'miniconda.sh'miniconda.sh 100%[=================>] 59.68M 5.97MB/s in 11s2018-09-1509:44:28 (5.42 MB/s) - 'miniconda.sh' saved [62574861/62574861]root@py4fi:~# bash miniconda.sh
Welcome to Miniconda34.5.11In order to continue the installation process, please review the license agreement.
Please, press ENTER to continue
>>>只需按Enter键即可开始安装过程。审阅许可协议后,回答yes以接受条款:
Do you accept the license terms? [yes|no]
[no] >>> yesMiniconda3 will now be installed into this location: /root/miniconda3- 按Enter确认位置
- 或在下面指定不同位置
[/root/miniconda3] >>>
PREFIX=/root/miniconda3
installing: python-3.7. ...
...
installing: requests-2.19.1-py37_0 ...
installing: conda-4.5.11-py37_0 ...
installation finished.同意许可条款并确认安装位置后,应再次回答yes,允许Miniconda将新的Miniconda安装位置添加到PATH环境变量中:
Do you wish the installer to prepend the Miniconda3 install location
to PATH in your /root/.bashrc ? [yes|no]
[no] >>> yesAppending source /root/miniconda3/bin/activate to /root/.bashrc A backup will be made to: /root/.bashrc-miniconda3.bak
要使此更改生效,必须打开一个新的终端。
Thank you for installing Miniconda3!
root@py4fi:~#之后,你可能想要升级conda和Python:³
root@py4fi:~# export PATH="/root/miniconda3/bin/:$PATH"
root@py4fi:~# conda update -y conda python
...
root@py4fi:~# echo "./root/miniconda3/etc/profile.d/conda.sh" >> ~/.bashrc
root@py4fi:~# bash完成这个相当简单的安装过程后,你将拥有基本的Python安装以及可用的conda。基本Python安装附带了一些不错的"电池",如SQLite3数据库引擎。你可以尝试在将相关路径添加到相应环境变量后(如前面所做),在新shell实例中启动Python:
root@py4fi:~# python
Python 3.7.0 (default, Jun 282018, 13:15:42)
[GCC 7.2.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> print('Hello Python for Finance World.')
Hello Python for Finance World.
>>> exit()
root@py4fi:~#conda的基本操作#
conda可用于高效地处理Python包的安装、更新和移除等操作。以下列表提供了主要功能的概览:
安装Python x.x
conda install python=x.x更新Python conda update python
安装包 conda install $PACKAGE_NAME
更新包 conda update $PACKAGE_NAME
移除包
conda remove $PACKAGE_NAME更新conda自身 conda update conda
搜索包
conda search $SEARCH_TERM列出已安装包 conda list
利用这些能力,安装例如NumPy——科学栈中最重要的库之一——只需要一个命令。当在配备Intel处理器的机器上安装时,该过程会自动安装Intel Math Kernel Library(mkl),它不仅加速NumPy,还能加速其他几个科学Python包的数值运算:⁴
root@py4fi:~# conda install numpy
Solving environment: done## Package Plan ##
environment location: /root/miniconda3
added / updated specs: - numpy
The following packages will be downloaded:
| package | build | |
| mkl-2019.0 | 117 | 204.4 MB |
| intel-openmp-2019.0 | 117 | 721 KB |
| mkl_random-1.0.1 | py37h4414c95_1 | 372 KB |
| libgfortran-ng-7.3.0 | hdf63c60_0 | 1.3 MB |
| numpy-1.15.1 | py37h1d66e8a_0 | 37 KB |
| numpy-base-1.15.1 | py37h81de0dd_0 | 4.2 MB |
| blas-1.0 | mkl | 6 KB |
| mkl_fft-1.0.4 | py37h4414c95_1 | 149 KB |
| Total: | 211.1 MB | |
The following NEW packages will be INSTALLED:
blas: 1.0-mkl intel-openmp: 2019.0-117 libgfortran-ng: 7.3.0-hdf63c60_0 mkl: 2019.0-117 mkl_fft: 1.0.4-py37h4414c95_1 mkl_random: 1.0.1-py37h4414c95_1
numpy: 1.15.1-py37h1d66e8a_0
numpy-base: 1.15.1-py37h81de0dd_0Proceed ([y]/n)? y
Downloading and Extracting Packages
mkl-2019.0 | 204.4 MB | ###########
| 100%
...
numpy-1.15.1 | 37 KB | ###########
| 100%
numpy-base-1.15.1 | 4.2 MB | ###########
| 100%
...
root@py4fi:~#多个包也可以同时安装。-y标志指示所有(潜在的)问题都回答yes:
root@py4fi:/# conda install -y ipython matplotlib pandas pytables scikit-learn \
> scipy...
pytables-3.4.4 | 1.5 MB | ###########
kiwisolver-1.0.1 | 83 KB | ###########
icu-58.2 | 22.5 MB | ###########
Preparing transaction: done
Verifying transaction: done
Executing transaction: done
root@py4fi:~#安装完成后,除了标准库外,金融分析中一些最重要的库也变得可用,包括:
IPython 改进的交互式Python shell matplotlib Python标准绘图库 NumPy 高效处理数值数组 pandas 管理表格数据,如金融时间序列数据 PyTables HDF5库的Python封装 scikit-learn 机器学习和相关任务的包 SciPy 科学类和函数的集合(作为依赖项安装)
这提供了数据分析(特别是金融分析)的基本工具集。下一个示例使用IPython,并用NumPy生成一组伪随机数:
root@py4fi:~# ipython
Python 3.7.0 (default, Jun 282018, 13:15:42)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.5.0 -- An enhanced Interactive Python. Type '?' for help.In [1]: import numpy as npIn [2]: np.random.seed(100)In [3]: np.random.standard_normal((5, 4))
Out[3]:
array([[-1.74976547, 0.3426804, 1.1530358, -0.25243604],
[0.98132079, 0.51421884, 0.22117967, -1.07004333],
[-0.18949583, 0.25500144, -0.45802699, 0.43516349],
[-0.58359505, 0.81684707, 0.67272081, -0.10441114],
[-0.53128038, 1.02973269, -0.43813562, -1.11831825]])In [4]: exit
root@py4fi:~#执行 conda list 可显示已安装的包:
root@py4fi:~# conda list
packages in environment at /root/miniconda3:| # Name | Version | Build | Channel |
| asn1crypto | 0.24.0 | py37_0 | |
| backcall | 0.1.0 | py37_0 | |
| blas | 1.0 | mkl | |
| blosc | 1.14.4 | hdbcaa40_0 | |
| bzip2 | 1.0.6 | h14c3975_5 | |
| ... | |||
| python | 3.7.0 | hc3d631a_0 | |
| ... | |||
| wheel | 0.31.1 | py37_0 | |
| xz | 5.2.4 | h14c3975_4 | |
| yaml | 0.1.7 | had09818_2 | |
| zlib | 1.2.11 | ha838bed_2 | |
| root@py4fi:~# | |||
如果某个包不再需要,可以用 conda remove 有效移除:
root@py4fi:~# conda remove scikit-learn
Solving environment: done## Package Plan ##
environment location: /root/miniconda3removed specs:
- scikit-learnThe following packages will be REMOVED:
scikit-learn: 0.19.1-py37hedc7406_0Proceed ([y]/n)? yPreparing transaction: done
Verifying transaction: done
Executing transaction: done
root@py4fi:~#conda作为包管理器已经相当有用。然而,它的全部力量只有在加入虚拟环境管理后才真正显现。
便捷的包管理
使用conda作为包管理器,安装、更新和移除Python包成为一种愉快的体验。无需自行构建和编译包——考虑到包指定的依赖项列表以及不同操作系统上的特定要求,这有时可能很棘手。
conda作为虚拟环境管理器#
根据你选择的安装程序版本,Miniconda提供默认的Python 2.7或3.7安装。conda的虚拟环境管理能力允许你在Python 3.7默认安装的基础上,添加一个完全独立的Python 2.7.x安装。为此,conda提供以下功能:
创建虚拟环境
conda create --name $ENVIRONMENT_NAME激活环境 conda activate $ENVIRONMENT_NAME
停用环境 conda deactivate $ENVIRONMENT_NAME
移除环境
conda env remove --name $ENVIRONMENT_NAME导出到环境文件
conda env export > $FILE_NAME从文件创建环境
conda env create -f $FILE_NAME列出所有环境
conda info --envs作为简单说明,以下示例代码创建了一个名为py27的环境,安装IPython,并执行一行Python 2.7.x代码:
root@py4fi:~# conda create --name py27 python=2.7
Solving environment: done
\## Package Plan ##
environment location: /root/miniconda3/envs/py27
added / updated specs:
- python=2.7The following NEW packages will be INSTALLED:
ca-certificates: 2018.03.07-0
...
python: 2.7.15-h1571d57_0
...
zlib: 1.2.11-ha838bed_2Preparing transaction: done
Verifying transaction: done
Executing transaction: done
#
To activate this environment, use:
> conda activate py27
#
To deactivate an active environment, use:
> conda deactivate
#注意激活环境后提示符如何变化,包含(py27):
root@py4fi:~# conda activate py27
(py27) root@py4fi:~# conda install ipython
Solving environment: done...
Executing transaction: done (py27) root@py4fi:~#最后,这使你能够使用Python 2.7语法的IPython:
(py27) root@py4fi:~# ipython
Python 2.7.15 |Anaconda, Inc.| (default, May 12018, 23:32:55)
Type "copyright", "credits" or "license" for more information.IPython 5.8.0 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.In [1]: print "Hello Python for Finance World!"
Hello Python for Finance World!In [2]: exit
(py27) root@py4fi:~#如本示例所示,使用conda作为虚拟环境管理器允许同时安装不同版本的Python。它还允许安装某些包的不同版本。默认的Python安装不受此类过程影响,同一台机器上可能存在的其他环境也不受影响。所有可用环境可通过 conda env list 显示:
(py27) root@py4fi:~# conda env list
conda environments:
#
base /root/miniconda3
py27 * /root/miniconda3/envs/py27(py27) root@py4fi:~#有时需要与他人共享环境信息,或在多台机器上使用环境信息。为此,可以使用 conda env export 将已安装的包列表导出到文件。默认情况下,这仅在机器使用相同操作系统时才能正常工作,因为生成的YAML文件中指定了构建版本,但可以删除它们以仅指定包版本:
(py27) root@py4fi:~# conda env export --no-builds > py27env.yml
(py27) root@py4fi:~# cat py27env.yml
name: py27
channels:
- defaults
dependencies:
- backports=1.0
...
- python=2.7.15- zlib=1.2.11
prefix: /root/miniconda3/envs/py27
(py27) root@py4fi:~#
通常,创建虚拟环境(技术上不过是一种特定的子文件夹结构)是为了进行一些快速测试。⁵ 在这种情况下,停用后可以通过 conda env remove 轻松移除环境:
(py27) root@py4fi:/# conda deactivate
root@py4fi:~# conda env remove -y --name py27
Remove all packages in environment /root/miniconda3/envs/py27:
## Package Plan ##
environment location: /root/miniconda3/envs/py27
The following packages will be REMOVED:
backports: 1.0-py27_1
zlib: 1.2.11-ha838bed_2
root@py4fi:~#
至此,conda作为虚拟环境管理器的概述结束。
便捷的环境管理
conda不仅有助于管理包,还充当Python的虚拟环境管理器。它简化了不同Python环境的创建,允许你在同一台机器上拥有多个版本的Python和可选包,而它们互不影响。conda还允许你导出环境信息,以便轻松地在多台机器上复制或与他人共享。
使用Docker容器#
Docker容器已经席卷了IT世界。虽然这项技术仍然相对年轻,但它已成为高效开发和部署几乎任何类型软件应用的基准之一。
就本书而言,将Docker容器视为一个独立的("容器化的")文件系统就足够了,它包含操作系统(如Ubuntu Server 18.04)、(Python)运行时、额外的系统和开发工具以及所需的(Python)库和包。这样的Docker容器可以运行在本地Windows 10机器上,也可以运行在带有Linux操作系统的云实例上。
本节不会深入探讨Docker容器的所有激动人心的细节。它只是简要说明Docker技术在Python部署方面的能力。⁶
Docker镜像与容器#
在继续说明之前,需要区分讨论Docker时的两个基本概念。第一个是Docker镜像(Docker image),可以类比为Python类。第二个是Docker容器(Docker container),可以类比为相应Python类的实例。⁷
在更技术的层面上,Docker词汇表中对镜像有如下定义:
Docker镜像是容器的基础。镜像是一个只读模板,包含创建容器的说明。镜像通常包含堆叠在彼此之上的分层文件系统的联合。镜像没有状态,永远不会改变。
类似地,Docker词汇表中对容器有如下定义,这使得与Python类和类实例的类比更加清晰:
容器是Docker镜像的可运行实例。一个Docker容器包含:一个Docker镜像、一个执行环境以及一组标准指令。
根据操作系统的不同,Docker的安装也有所不同。这就是本节不深入细节的原因。更多信息和相关链接可以在About Docker CE页面上找到。
构建Ubuntu和Python的Docker镜像#
本节说明如何基于最新版本的Ubuntu构建包含Miniconda以及一些重要Python包的Docker镜像。此外,它还进行一些Linux常规维护,如更新Linux包索引、必要时升级包以及安装某些额外的系统工具。为此,需要两个脚本。一个是bash脚本,负责Linux层面的所有工作。⁸ 另一个是所谓的Dockerfile,用于控制镜像本身的构建过程。
示例2-1中的安装bash脚本由三个主要部分组成。第一部分处理Linux常规维护。第二部分安装Miniconda,而第三部分安装可选的Python包。内联提供了更详细的注释。
示例2-1. 安装Python和可选包的脚本
#!/bin/bash
#
### 安装Linux系统工具和基础Python组件的脚本
#
#
通用Linux设置
apt-get update # 更新包索引缓存
apt-get upgrade -y # 更新包
安装系统工具
apt-get install -y bzip2 gcc git htop screen vim wget
apt-get upgrade -y bash # 必要时升级bash
apt-get clean # 清理包索引缓存
安装Miniconda
下载Miniconda
wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -0 \ Miniconda.sh
bash Miniconda.sh -b # 安装Miniconda
rm -rf Miniconda.sh # 删除安装程序
export PATH="/root/miniconda3/bin:$PATH" # 预置新路径
安装Python库
conda update -y conda python # 更新conda和Python(如果需要)conda install -y pandas # 安装pandas
conda install -y ipython # 安装IPython shell示例2-2中的Dockerfile使用示例2-1中的bash脚本构建一个新的Docker镜像。其中也内联注释了主要部分。
示例2-2. 构建镜像的Dockerfile
#
### 使用最新Ubuntu版本和基础Python安装构建Docker镜像
#
#
最新的Ubuntu版本
FROM ubuntu:latest
维护者信息
MAINTAINER yves
添加bash脚本
ADD install.sh/
修改脚本权限
RUN chmod u+x /install.sh
运行bash脚本
RUN /install.sh
预置新路径
ENV PATH /root/miniconda3/bin:$PATH
容器运行时执行IPython
CMD ["ipython"]如果这两个文件位于同一文件夹中并且Docker已安装,则构建新Docker镜像的过程非常简单。这里为镜像使用了标签 py4fi:basic。该标签在后续引用镜像时使用,例如在运行基于它的容器时:
~/Docker$ docker build -t py4fi:basic .
...
Removing intermediate container 5fec0c9b2239
----> accee128d9e9
Step 6/7 : ENV PATH /root/miniconda3/bin:$PATH
----> Running in a2bb97686255
In [3]: import pandas as pdIn [1]: import numpy as npRemoving intermediate container a2bb97686255
---> 73b00c215351
Step 7/7 : CMD ["ipython"]
---> Running in ec7acd90c991
Removing intermediate container ec7acd90c991
---> 6c36b9117cd2
Successfully built 6c36b9117cd2
Successfully tagged py4fi:basic
~/Docker$现有的Docker镜像可以通过 docker images 列出。新镜像应位于列表顶部:
(py4fi) ~/Docker$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
py4fi basic 6c36b9117cd2 About a minute ago 1.79GB
ubuntu latest cd6d8154f1e19 days ago 84.1MB
(py4fi) ~/Docker$成功构建 py4fi:basic 后,可以使用 docker run 运行相应的Docker容器。参数组合 -ti 用于在Docker容器内运行的交互式进程,如shell进程(参见docker run参考页面):
~/Docker$ docker run -ti py4fi:basic
Python 3.7.0 (default, Jun 282018, 13:15:42)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.5.0 -- An enhanced Interactive Python. Type '?' for help.In [2]: a = np.random.standard_normal((5, 3))In [4]: df = pd.DataFrame(a, columns=['a', 'b', 'c'])In [6]:退出IPython也会退出容器,因为它是容器内运行的唯一应用程序。不过,你可以通过键入Ctrl-P + Ctrl-Q从容器中分离。
在分离后,docker ps 命令仍会显示正在运行的容器(以及任何其他当前正在运行的容器):
~/Docker$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS
e815df8f0f4d py4fi:basic "ipython" About a minute ago Up About a minute
4518917de7dc ubuntu:latest "/bin/bash" About an hour ago Up About an hour
d081b5c7add0 ubuntu:latest "/bin/bash" 21 hours ago Up 21 hours
~/Docker$附加到Docker容器使用命令 docker attach $CONTAINER_ID(注意 $CONTAINER_ID 只需输入前几个字符即可):
~/Docker$ docker attach e815d#
In [6]: df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5 entries, 0 to 4
Data columns (total 3 columns):
a 5 non-null float64
b 5 non-null float64
c 5 non-null float64
dtypes: float64(3)
memory usage: 200.0 bytesIn [7]: exit ~/Docker$exit 命令终止IPython并停止Docker容器。可以使用 docker rm 移除它:
~/Docker$ docker rm e815d
e815d
~/Docker$类似地,如果不再需要Docker镜像 py4fi:basic,可以通过 docker rmi 移除。虽然容器相对轻量,但单个镜像可能消耗相当大的存储空间。对于 py4fi:basic 镜像,大小接近2 GB。这就是为什么你可能想要定期清理Docker镜像列表:
~/Docker$ docker rmi 6c36b9117cd2#
当然,关于Docker容器及其在某些应用场景中的优势还有更多内容可谈。但就本书而言,了解它们提供了部署Python、在完全独立的(容器化)环境中进行Python开发以及为算法交易发布代码的现代方法,就足够了。
Docker容器的优势
如果你尚未使用Docker容器,应考虑使用。它们在Python部署和开发工作方面提供了许多优势,不仅是在本地工作时,尤其是在使用远程云实例和部署算法交易代码的服务器时。
使用云实例#
本节展示如何在DigitalOcean云实例上建立完整的Python基础设施。市面上还有许多其他云提供商,包括领先提供商亚马逊网络服务(AWS)。然而,DigitalOcean以其简洁性和相对低廉的小型云实例(称为Droplet)费率而闻名。最小的Droplet(通常足以满足探索和开发目的)每月仅需5美元,或每小时0.007美元。使用按小时计费,因此你可以轻松启动一个Droplet使用2小时,然后销毁它,仅需支付0.014美元。⁹
本节的目标是在DigitalOcean上建立一个Droplet,配备Python 3.7安装及通常需要的包(如NumPy、pandas),并配合密码保护和安全套接层(SSL)加密的Jupyter Notebook服务器安装。该服务器安装将提供三种可通过常规浏览器使用的主要工具:
Jupyter Notebook 一个流行的交互式开发环境,内置多种语言内核(如Python、R和Julia)。
终端 可通过浏览器访问的系统shell实现,允许所有典型的系统管理任务,并使用Vim和git等有用工具。
编辑器 基于浏览器的文件编辑器,支持多种编程语言和文件类型的语法高亮,以及典型的文本/代码编辑能力。
在Droplet上安装Jupyter Notebook后,你可以通过浏览器进行Python开发和部署,无需通过安全外壳(SSH)访问登录云实例。
为实现本节的目标,需要以下文件:
服务器设置脚本 该脚本协调所有必要的步骤,例如将其他文件复制到Droplet并在其上运行。
Python和Jupyter安装脚本 安装Python、附加包和Jupyter Notebook,并启动Jupyter Notebook服务器。
Jupyter Notebook配置文件 用于配置Jupyter Notebook服务器,如密码保护等。
以下小节将反向逐一介绍这些文件。
RSA公钥和私钥#
为了通过任意浏览器创建到Jupyter Notebook服务器的安全连接,需要由RSA公钥和私钥组成的SSL证书。通常,这样的证书应来自所谓的证书颁发机构(CA)。然而就本书而言,自生成的证书"足够好"。¹⁰ 生成RSA密钥对的一个流行工具是OpenSSL。以下简短交互式会话展示了如何生成适用于Jupyter Notebook服务器的证书(根据提示输入你自己的国家名称和其他字段值):
~/cloud$ openssl req -x509 -nodes -days 365 -newkey \
> rsa:1024 -out cert.pem -keyout cert.key
Generating a 1024 bit RSA private key
..++++++
......++++++
writing new private key to 'cert.key'You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank.
Country Name (2 letter code) [AU]:DE
State or Province Name (full name) [Some-State]:Saarland
Locality Name (eg, city) []:VoelklingenOrganization Name (eg, company) [Internet Widgits Pty Ltd]:TPQ GmbH
Organizational Unit Name (eg, section) []:Python for Finance
Common Name (e.g. server FQDN or YOUR name) []:Jupyter
Email Address []:team@tpq.io
~/cloud$ ls
cert.key cert.pem
~/cloud$两个文件 cert.key 和 cert.pem 需要复制到Droplet,并在Jupyter Notebook配置文件中引用。接下来介绍该文件。
Jupyter Notebook配置文件#
正如文档中所解释的,公共Jupyter Notebook服务器可以安全部署。Jupyter Notebook的功能之一是密码保护。为此,notebook.auth 子包中有一个名为 passwd() 的密码哈希码生成函数。以下代码生成了一个密码哈希码,其中 jupyter 为密码本身:
~/cloud$ ipython
Python 3.7.0 (default, Jun 282018, 13:15:42)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.5.0 -- An enhanced Interactive Python. Type '?' for help.In [1]: from notebook.auth import passwd
In [2]: passwd('jupyter')
Out[2]: 'sha1:d4d34232ac3a:55ea0ffd78cc3299e3e5e6ecc0d36be0935d424b'In [3]: exit此哈希码需要放置在示例2-3所示的Jupyter Notebook配置文件中。该配置文件假定RSA密钥文件已复制到Droplet的 /root/.jupyter/ 文件夹。
示例2-3. Jupyter Notebook配置文件
#
### Jupyter Notebook配置文件
#
#
SSL加密
将以下文件名(以及使用的文件)替换为你自己的选择/文件
c. NotebookApp.certfile = u'/root/.jupyter/cert.pem'
c. NotebookApp.keyfile = u'/root/.jupyter/cert.key'
IP地址和端口
设置ip为'*'以绑定云实例的所有IP地址c. NotebookApp.ip = '*'
建议设置一个已知的、固定的默认端口用于服务器访问
c. NotebookApp.port = 8888
密码保护
此处:密码为'jupyter'
将哈希码替换为你强密码对应的哈希码
c. NotebookApp.password = 'sha1:d4d34232ac3a:55ea0ffd78cc3299e3e5e6ecc0d36be0935d424b'
不启动浏览器选项
防止Jupyter尝试打开浏览器
c. NotebookApp.open_browser = FalseJupyter与安全
在云端部署Jupyter Notebook主要会带来一些安全问题,因为它是可通过Web浏览器访问的完整开发环境。因此,使用Jupyter Notebook服务器默认提供的安全措施(如密码保护和SSL加密)至关重要。但这只是开始;根据云实例上的具体操作,可能还需要进一步的安全措施。
下一步是确保Python和Jupyter Notebook安装在Droplet上。
Python和Jupyter Notebook的安装脚本#
安装Python和Jupyter Notebook的bash脚本与"使用Docker容器"一节中通过Miniconda在Docker容器中安装Python的脚本类似。然而,示例2-4中的脚本还需要启动Jupyter Notebook服务器。所有主要部分和代码行都有内联注释。
示例2-4. 安装Python并运行Jupyter Notebook服务器的bash脚本
#!/bin/bash
#
### 安装Linux系统工具、基础Python包和Jupyter Notebook服务器的脚本
#
#
通用Linux设置
apt-get update # 更新包索引缓存apt-get upgrade -y # 更新包
apt-get install -y bzip2 gcc git htop screen vim wget # 安装系统工具
apt-get upgrade -y bash # 必要时升级bash
apt-get clean # 清理包索引缓存
安装Miniconda
wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -0 \ Miniconda.sh
bash Miniconda.sh -b # 安装Miniconda
rm Miniconda.sh # 删除安装程序
为当前会话预置新路径
export PATH="/root/miniconda3/bin:$PATH"
在shell配置中预置新路径
echo ". /root/miniconda3/etc/profile.d/conda.sh" >> ~/.bashrc
echo "conda activate" >> ~/.bashrc
安装Python库
可以根据用例添加更多包
conda update -y conda # 必要时更新conda
conda create -y -n py4fi python=3.7 # 创建环境
source activate py4fi # 激活新环境
conda install -y jupyter # 浏览器中的交互式数据分析
conda install -y pytables # HDF5二进制存储封装
conda install -y pandas # 数据分析包
conda install -y matplotlib # 标准绘图库
conda install -y scikit-learn # 机器学习库
conda install -y openpyxl # Excel交互库
conda install -y pyyaml # YAML文件管理库
pip install --upgrade pip # 升级包管理器
pip install cufflinks # 将plotly与pandas结合
复制文件和创建目录
mkdir /root/.jupyter
mv /root/jupyter_notebook_config.py /root/.jupyter/
mv /root/cert.* /root/.jupyter
mkdir /root/notebook
cd /root/notebook
启动Jupyter Notebook
jupyter notebook --allow-root
以后台进程方式启动Jupyter Notebook
jupyter notebook --allow-root &此脚本需要复制到Droplet,并由下一小节描述的组织脚本启动。
组织Droplet设置的脚本#
第二个bash脚本(用于设置Droplet)是最短的(示例2-5)。它主要将所有其他文件复制到Droplet(其IP地址作为参数传入)。最后一行启动 install.sh bash脚本,该脚本执行安装本身并启动Jupyter Notebook服务器。
示例2-5. 设置Droplet的bash脚本
#!/bin/bash
#
### 设置DigitalOcean Droplet
### 基础Python栈和Jupyter Notebook
#
#
从参数获取IP地址
MASTER_IP=$1
复制文件
scp install.sh root@$MASTER_IP):
scp cert.* jupyter_notebook_config.py root@$MASTER_IP):
执行安装脚本
ssh root@$MASTER_IP} bash /root/install.sh现在一切都就绪,可以尝试设置代码。在DigitalOcean上,使用类似以下选项创建一个新的Droplet:
操作系统 Ubuntu 18.10 x64(撰写本文时可用的最新版本) 规格 1核,1 GB,25 GB SSD(最小的Droplet) 数据中心区域 法兰克福(因为作者居住在德国) SSH密钥 添加(新的)SSH密钥用于免密码登录 ¹¹ Droplet名称 可以使用预设名称,或选择如py4fi之类的名称
点击Create按钮将启动Droplet创建过程,通常需要约一分钟。设置过程的主要成果是IP地址,例如,如果你选择法兰克福作为数据中心位置,IP地址可能是46.101.156.199。现在设置Droplet非常简单:
(py3) ~/cloud$ bash setup.sh 46.101.156.199
整个过程可能需要几分钟。当Jupyter Notebook服务器显示类似以下消息时,表示完成:
The Jupyter Notebook is running at: https://[all ip addresses on your system]:8888/
在任何现代浏览器中,访问以下地址即可连接到正在运行的Jupyter Notebook服务器(注意https协议):
在可能要求你添加安全例外后,Jupyter Notebook登录屏幕将提示输入密码(此处为jupyter)。现在你就可以通过Jupyter Notebook在浏览器中开始Python开发,通过终端窗口使用IPython,或使用文本文件编辑器。其他文件管理功能(如文件上传、文件删除和文件夹创建)也同样可用。
云的优势
DigitalOcean等云实例与Jupyter Notebook的结合是一个强大的组合,使Python开发者和量化分析师能够使用专业的计算和存储基础设施。专业的云和数据中心提供商确保你的(虚拟)机器物理安全且高可用。使用云实例还能使探索和开发阶段的成本保持在较低水平,因为使用通常按小时计费,无需签订长期合同。
结论#
Python是首选编程语言和技术平台——不仅对本书而言如此,对几乎所有领先金融机构也是如此。然而,Python部署充其量可能很棘手,有时甚至令人厌倦和紧张。幸运的是,近年来出现了几种有助于解决部署问题的技术。开源conda在Python包和虚拟环境管理两方面都有帮助。Docker容器则更进一步,可以在技术上屏蔽的"沙箱"(即容器)中轻松创建完整的文件系统和运行时环境。再进一步,DigitalOcean等云提供商在专业管理和保护的数据中心内,在几分钟内提供按小时计费的计算和存储容量。这与Python 3.7安装和安全Jupyter Notebook服务器安装的结合,为Python开发和在Python-for-finance项目背景下的部署提供了专业环境。
延伸阅读#
关于Python包管理,请参阅以下资源:
• pip包管理器页面 • conda包管理器页面 • Installing Packages页面
关于虚拟环境管理,请参阅以下资源:
• virtualenv环境管理器页面 • conda Managing Environments页面 • pipenv包和环境管理器
以下资源(以及其他)提供关于Docker容器的信息:
• Docker首页 • Matthias, Karl, and Sean Kane (2015). Docker: Up and Running. Sebastopol, CA: O'Reilly.
关于bash脚本语言的简要介绍和概述,请参阅:
• Robbins, Arnold (2016). Bash Pocket Reference. Sebastopol, CA: O'Reilly.
如何安全运行公共Jupyter Notebook服务器在Jupyter Notebook文档中有说明。还有一个名为JupyterHub的hub,允许多用户管理Jupyter Notebook服务器。
要在DigitalOcean上注册并获得新账户10美元起始余额,请访问 http://bit.ly/do_sign_up。这足以支付最小Droplet两个月的使用费用。
掌握基础#
本书的这一部分涉及Python编程的基础知识。本部分涵盖的主题对所有后续章节以及Python的常规使用都是基础性的。
各章按主题组织,可以作为读者查阅感兴趣主题相关示例和详细信息的参考资料:
• 第3章 重点介绍Python数据类型和结构。 • 第4章 介绍NumPy及其ndarray类。 • 第5章 介绍pandas及其DataFrame类。 • 第6章 讨论Python面向对象编程(OOP)。