蓋房子的時候,木料的選擇是個問題。
木匠的目標本質上就是攜帶好的切割工具。在他有時間的時候,會將他的設備磨得很鋒利。
{–:}——宮本武藏(五輪書)
本文摘自《Python大數據分析(第2版)》第2章
對於Python新手來說,Python的部署似乎很簡單。豐富的可選安裝庫和程序包也很容易安裝。首先,Python不止一種,它有許多不同的“風味”,如CPython、Jython、IronPython和PyPy。然後,Python 2.7和3.x也是不同的世界。[1]
即便在你決定了使用版本之後,部署也很困難,原因如下:
- 解釋程序(標準CPython安裝)只帶有所謂的“標準庫”(例如,包含了典型的數學函數);
- 可選的Python軟件包必須單獨安裝,它們有數百種之多;
- 由於依賴性和操作系統的特定需求,自行編譯/構建這些非標準包可能很困難;
- 需要隨時注意依賴性和版本一致性(也就是維護工作),這乏味且費時;
- 某些包的更新升級可能需要重新編譯許多其他的軟件包;
- 更新或者替換一個包,可能在其他(許多)地方造成麻煩。
幸運的是,我們可以求助於工具和策略。本章將介紹以下有助於Python部署的技術。
包管理器
pip和conda等包管理器用於安裝、更新和刪除Python軟件包;它們還有助於保持不同包的版本一致性。
虛擬環境管理器
virtualenv或 conda等虛擬環境管理器可以並行管理多種Python安裝(例如,在單一機器上安裝Python 2.7和3.7,以便無風險地測試某個有趣的Python軟件包的最新開發版本)。[2]
容器
Docker容器代表着包含運行特定軟件所需的全部系統部件(如代碼、運行時庫或系統工具)的完整文件系統。例如,你可以在運行macOS或者Windows10的一臺機器上,在一個Docker容器裏運行Ubuntu 18.04操作系統,並在其中安裝Python 3.7和單獨的Python代碼。
雲實例
爲金融應用部署Python代碼通常要求高可用性、安全性和高性能;這些需求一般只能利用專業計算及存儲基礎設施滿足。目前,這種基礎設施以情況良好的雲實例形式存在,規模從小到不等。與長期租賃的專用服務器相比,雲實例(也就是虛擬服務器)的好處之一是,用戶通常只需要按照實際使用的時間付費;另一個好處是,這種雲實例在需要時一兩分鐘內就能投入使用,有助於敏捷開發並提高伸縮性。
本章的結構如下。
作爲包管理器使用的Conda
本節介紹作爲Python包管理器使用的Conda。
作爲虛擬環境管理器使用的Conda
這一節專注於conda作爲虛擬環境管理器的功能。
使用Docker容器
這一節簡單概述了Docker容器化技術,聚焦於構建帶有Python 3.7安裝的Ubuntu容器。
使用雲實例
本節介紹在雲中部署Python和Jupyter Notebook的方法,後者是一個基於瀏覽器的、功能強大的Python部署工具套件。
本章的目標是在專業基礎設施上建立一個合適的Python環境,包含最重要的工具以及數值、數據分析和可視化軟件包(庫)。此後,這一組合將作爲實現和部署後續章節中Python代碼的支柱,不管這些代碼是交互式的金融分析代碼,還是以腳本和模塊形式出現的。
1.1 作爲包管理器使用的conda
conda可以單獨安裝,但是更有效的方法之一是通過Miniconda安裝,這是一個包含conda、並將conda作爲包和虛擬環境管理器使用的最小化Python分發版本。
1.1.1 安裝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 \
> -O 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 11s
2018-09-15 09:44:28 (5.42 MB/s) - 'miniconda.sh' saved [62574861/62574861]
root@py4fi:~# bash miniconda.sh
Welcome to Miniconda3 4.5.11
In 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] >>> yes
Miniconda3 will now be installed into this location:
/root/miniconda3
- Press ENTER to confirm the location
- Press CTRL-C to abort the installation
- Or specify a different location below
[/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] >>> yes
Appending source /root/miniconda3/bin/activate to /root/.bashrc
A backup will be made to: /root/.bashrc-miniconda3.bak
For this change to become active, you have to open a new terminal.
Thank you for installing Miniconda3!
root@py4fi:~#
此後,你可能想要升級conda和Python。[3]
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 28 2018, 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:~#
2.1.2 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數學核心庫(Intel Math Kernel Library,MKL),這個庫不僅能加速NumPy的數值運算,而且對其他幾個Python科學庫也有作用。[4]
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_0
Proceed ([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 | ##################################### | 100%
kiwisolver-1.0.1 | 83 KB | ##################################### | 100%
icu-58.2 | 22.5 MB | ##################################### | 100%
Preparing transaction: done
Verifying transaction: done
Executing transaction: done
root@py4fi:~#
安裝過程結束後,除了標準庫之外,一些重要的金融分析庫也已經可用,包括:
Ipython
改進的交互式Python shell;
matplotlib
Python標準繪圖庫;
NumPy
用於高效處理數組;
pandas
用於管理表格數據,例如金融時間序列數據;
PyTables
Python HDF5庫封裝器;
scikit-learn
機器學習和相關任務所用的軟件包;
SciPy
一組科學類和函數(以依賴的形式安裝)。
這就爲數據分析、特別是金融分析提供了一個基本工具集。下面的例子使用IPython和NumPy提取了一組僞隨機數。
root@py4fi:~# ipython
Python 3.7.0 (default, Jun 28 2018, 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 np
In [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/miniconda3
removed specs:
- scikit-learn
The following packages will be REMOVED:
scikit-learn: 0.19.1-py37hedc7406_0
Proceed ([y]/n)? y
Preparing transaction: done
Verifying transaction: done
Executing transaction: done
root@py4fi:~#
conda的包管理器功能相當實用。然而,在加上虛擬環境管理器後,你才能看出它的全部威力。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-J6n4OCQP-1582770738682)(/api/storage/getbykey/screenshow?key=18013c684ffc590e9219)]
簡易包管理
conda做爲包管理器,可以使Python軟件包的安裝、更新和刪除變得很簡單。沒有必要自行構建和編譯軟件包——考慮到軟件包指定的依賴列表和不同操作系統所需考慮的細節,這一步有時可能很棘手。
2.2 作爲虛擬環境管理器的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.7
The following NEW packages will be INSTALLED:
ca-certificates: 2018.03.07-0
...
python: 2.7.15-h1571d57_0
...
zlib: 1.2.11-ha838bed_2
Proceed ([y]/n)? y
Preparing transaction: done
Verifying transaction: done
Executing transaction: done
#
# To activate this environment, use:
# > conda activate py27
#
# To deactivate an active environment, use:
# > conda deactivate
#
root@py4fi:~#
注意激活環境之後提示符的變化(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 1 2018, 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:~#
從技術上說,虛擬環境不過是一個特定的(子)文件夾結構,創建它們往往是爲了進行一些快速測試[5]。在這種情況下,停止後的環境很容易用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的虛擬環境管理器的功能概述到此結束。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-2yaSY054-1582770738683)(/api/storage/getbykey/screenshow?key=18013c684ffc590e9219)]
簡易環境管理
conda不僅有助於包管理,還是Python的虛擬環境管理器。它簡化了不同Python環境的創建,允許在同一臺機器上使用多個版本的Python和可選包,這些不同版本不會互相影響。conda還可以導入環境信息,因此你可以輕鬆地在多臺機器上覆制環境,或者與他人共享。
2.3 使用Docker容器
Docker容器已經征服了IT界。雖然這種技術仍然相對年輕,但已經爲幾乎所有類型軟件應用的高效開發與部署確立了一個標杆。
在本書中,你可以將Docker容器看作一個獨立(“容器化”)文件系統,它包含操作系統(例如Ubuntu Sercer 18.04)、(Python)運行時庫、其他系統與開發工具,以及需要的其他(Python)庫和軟件包。這樣的一個Docker容器可以運行在Windows 10本地機器上,或者使用Linux操作系統的雲實例上。
本節不打算介紹Docker容器所有激動人心的細節,而是簡潔地說明Docker技術在Python開發領域所能發揮的能力。[6]
2.3.1 Docker鏡像和容器
不過,在說明之前,我們必須區分Docker的兩個基本概念。首先是Docker鏡像(Image),它可以比作Python的一個類。其次是Docker容器,它可以比作對應Python類的一個實例。[7]
您可以從Docker詞彙表上找到鏡像更爲技術性的定義:
Docker鏡像是容器的基礎。鏡像是根文件系統變化和用於容器運行時庫內部的對應執行參數的一個有序集合。鏡像通常包含一組相互堆疊的分層文件系統,它沒有狀態,也永遠不會變化。
類似地,您可以在Docker詞彙表上找到容器的定義,這使得與Python類和類實例的對比變得很清晰:
容器是Docker鏡像的運行時實例。一個Docker實例包括:一個Docker鏡像、一個執行環境和一個標準指令集。
根據操作系統的不同,Docker的安裝略有不同,這就是本節不做詳述的原因。更多的信息和鏈接可以在About Docker CE頁面上找到。
2.3.2 構建Ubuntu和Python Docker鏡像
本節舉例說明基於Ubuntu最新版本的Docker鏡像的構建方法,鏡像中還包括Miniconda和幾個重要的Python軟件包。此外,通過更新Linux軟件包索引、在必要時升級軟件包並安裝某些附加的系統工具,我們可以進行一些Linux的“內務整理”工作。這方面的工作需要兩個腳本,一個是完成所有Linux層面工作的bash腳本[8]。另一個是所謂的Dockerfile,即控制鏡像本身的構建過程。
例2-1中的bash安裝腳本包括3個主要部分。第一部分處理Linux“內務”。第二部分安裝Miniconda,而第3部分安裝Python可選程序包。更詳細的註釋請見腳本。
例2-1 安裝Python和可選包的腳本
#!/bin/bash
#
# Script to Install
# Linux System Tools and
# Basic Python Components
#
# Python for Finance, 2nd ed.
# (c) Dr. Yves J. Hilpisch
#
# GENERAL LINUX
apt-get update # updates the package index cache
apt-get upgrade -y # updates packages
# installs system tools
apt-get install -y bzip2 gcc git htop screen vim wget
apt-get upgrade -y bash # upgrades bash if necessary
apt-get clean # cleans up the package index cache
# INSTALL MINICONDA
# downloads Miniconda
wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O \
Miniconda.sh
bash Miniconda.sh -b # installs it
rm -rf Miniconda.sh # removes the installer
export PATH="/root/miniconda3/bin:$PATH" # prepends the new path
# INSTALL PYTHON LIBRARIES
conda update -y conda python # updates conda & Python (if required)
conda install -y pandas # installs pandas
conda install -y ipython # installs IPython shell
例2-2中的Dockerfile使用例2-1中的bash腳本,從而構建了一個新的Docker鏡像。它的主要部分也有內嵌註釋。
例2-2 構建鏡像的Dockerfile
#
# Building a Docker Image with
# the Latest Ubuntu Version and
# Basic Python Install
#
# Python for Finance, 2nd ed.
# (c) Dr. Yves J. Hilpisch
#
# latest Ubuntu version
FROM ubuntu:latest
# information about maintainer
MAINTAINER yves
# add the bash script
ADD install.sh /
# change rights for the script
RUN chmod u+x /install.sh
# run the bash script
RUN /install.sh
# prepend the new path
ENV PATH /root/miniconda3/bin:$PATH
# execute IPython when container is run
CMD ["ipython"]
如果這兩個文件在一個文件夾裏且安裝了Docker,那麼構建新鏡像就很簡單了。這裏爲鏡像使用了ubuntupython
標籤,這個標籤是引用鏡像時必需的,例如在根據它運行容器時。
~/Docker$ docker build -t py4fi:basic .
...
Removing intermediate container 5fec0c9b2239
---> accee128d9e9
Step 6/7 : ENV PATH /root/miniconda3/bin:$PATH
---> Running in a2bb97686255
Removing 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 f789dd230d6f About a minute ago 1.79GB
ubuntu latest cd6d8154f1e1 9 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 28 2018, 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 np
In [2]: a = np.random.standard_normal((5, 3))
In [3]: import pandas as pd
In [4]: df = pd.DataFrame(a, columns=['a', 'b', 'c'])
In [5]: df
Out[5]:
A b c
0 -1.412661 -0.881592 1.704623
1 -1.294977 0.546676 1.027046
2 1.156361 1.979057 0.989772
3 0.546736 -0.479821 0.693907
4 -1.972943 -0.193964 0.769500
In [6]:
退出IPython也將退出該容器,因爲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 agoUp About an hour
d081b5c7add0 ubuntu:latest "/bin/bash" 21 hours ago Up 21 hours
~/Docker$
Docker容器的連接可用docker attach 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 bytes
In [7]: exit
~/Docker$
exit
命令會終止IPython並停止Docker容器。容器可用docker rm
刪除:
~/Docker$ docker rm e815d
e815d
~/Docker$
類似地,如果不再需要Docker容器py4fi:basic
,可以通過docker rmi
刪除。雖然容器相對輕量,但單獨容器仍可能消耗相當一部分存儲容量。以py4fi:basic
爲例,其大小接近2GB。這也就是您可能想要定期清理Docker鏡像列表的原因:
~/Docker$ docker rmi 6c36b9117cd2
當然,關於Docker容器及其在某些應用場景中的好處,還有許多值得的講解。但對於本書,您只需要知道,容器爲部署Python、在完全獨立(容器化)的環境中完成Python開發和爲交付算法交易代碼提供了一種現代化方法,就足夠了。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-gm2xDST8-1582770738684)(/api/storage/getbykey/screenshow?key=18013c684ffc590e9219)]
Docker容器的好處
如果您還沒有使用Docker容器,應該考慮試試它。它們爲Python部署與開發工作提供了許多好處,不僅在本地工作時如此,在使用遠程雲實例與服務器部署算法交易代碼時更具優勢。
2.4 使用雲實例
本節介紹在DigitalOcean雲實例上建立全套Python基礎架構的方法。其他的雲提供商還有很多,如業界領先的Amazon Web Services。但是Digital Ocean以簡易而聞名,對於小型雲實例(稱作水滴(Droplet))來說,價格也相對低。研究和開發通常使用最小的Droplet就足夠了,其費用只有每月5美元(或者每小時0.007美元)。收費按小時計算,因此人們可以輕鬆地使用一個Droplet兩個小時,然後將其刪除,這只需要支付0.014美元。[9]
本節的目標是在DigitalOcean上建立一個Droplet,它包含Python 3.7安裝包和典型的軟件包(例如Numpy、Pandas),並與一個密碼保護、用安全套接字層(SSL)加密的Jupyter Notebook服務器安裝相結合。這個服務器安裝將提供3個可通過常規瀏覽器使用的重要工具。
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服務器SSL加密時所需的。
下面的小節以相反的次序來處理上述文件。
2.4.1 RSA公鑰和私鑰
爲了通過任意瀏覽器建立與Jupyter Notebook服務器的安全連接,我們需要一個包含RSA公鑰和私鑰的SSL證書。一般來說,這樣的證書來自所謂的證書頒發機構(CA)。但是,在本書中,自生成的證書就“足夠好”了。[10]生成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'
系統將要求您輸入加進證書請求中的信息。您將輸入所謂的可識別名稱(DN)。需要輸入的字段有多個,但您可以將某些留空,其他一些則用默認值。如果輸入“.”,字段將留空:
Country Name (2 letter code) [AU]:DE
State or Province Name (full name) [Some-State]:Saarland
Locality Name (eg, city) []:Voelklingen
Organization 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 []:[email protected]
~/cloud$ ls
cert.key cert.pem
~/cloud$
cert.key和cert.pem這兩個文件必須複製到Droplet中,由Jupyter Notebook配置文件引用。下面介紹配置文件。
2.4.2 Jupyter Notebook配置文件
您可以按照Jupyter Notebook文檔中的解釋,部署一個公共Jupyter Notebook服務器。除了其他特性之外,Jupyter Notebook還可以加上密碼保護。爲此,notebook.auth
子軟件包提供了一個密碼散列代碼生成函數passwd()
。以下代碼生成密碼爲jupyter的散列代碼:
~/cloud$ ipython
Python 3.7.0 (default, Jun 28 2018, 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 Configuration File
#
# Python for Finance, 2nd ed.
# (c) Dr. Yves J. Hilpisch
#
# SSL ENCRYPTION
# replace the following filenames (and files used) with your choice/files
c.NotebookApp.certfile = u'/root/.jupyter/cert.pem'
c.NotebookApp.keyfile = u'/root/.jupyter/cert.key'
# IP ADDRESS AND PORT
# set ip to '*' to bind on all IP addresses of the cloud instance
c.NotebookApp.ip = '*'
# it is a good idea to set a known, fixed default port for server access
c.NotebookApp.port = 8888
# PASSWORD PROTECTION
# here: 'jupyter' as password
# replace the hash code with the one for your strong password
c.NotebookApp.password = 'sha1:d4d34232ac3a:55ea0ffd78cc3299e3e5e6ecc0d36be0935d424b'
# NO BROWSER OPTION
# prevent Jupyter from trying to open a browser
c.NotebookApp.open_browser = False
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-7snKWGbT-1582770738685)(/api/storage/getbykey/screenshow?key=18013c684ffc590e9219)]
Jupyter與安全性
在雲端部署Jupyter Notebook會引起一些安全問題,因爲這是一個通過瀏覽器訪問的完整開發環境。因此,最重要的是使用Jupyter Notebook服務器提供的安全措施,例如密碼保護和SSL加密。但這只是開始:建議根據在雲實例上完成的工作採取進一步的安全措施。
下一步是確保將Python和Jupyter Notebook安裝在Droplet上。
2.4.2 Python和Jupyter Notebook安裝腳本
安裝 Python 和 Jupyter Notebook 的 bash 腳本與 2.3 小節中通過 Docker 容器裏的Miniconda安裝Python的腳本類似。但是,例2-4中的腳本還需要啓動Jupyter Notebook服務器。所有的重要部分和代碼行都有內嵌註釋。
例2-4 安裝Python和運行Jupyter Notebook服務器的bash腳本
#!/bin/bash
#
# Script to Install
# Linux System Tools,
# Basic Python Packages and
# Jupyter Notebook Server
#
# Python for Finance, 2nd ed.
# (c) Dr. Yves J. Hilpisch
#
# GENERAL LINUX
apt-get update # updates the package index cache
apt-get upgrade -y # updates packages
apt-get install -y bzip2 gcc git htop screen vim wget # installs system tools
apt-get upgrade -y bash # upgrades bash if necessary
apt-get clean # cleans up the package index cache
# INSTALLING MINICONDA
wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_
64.sh -O \
Miniconda.sh
bash Miniconda.sh -b # installs Miniconda
rm Miniconda.sh # removes the installer
# prepends the new path for current session
export PATH="/root/miniconda3/bin:$PATH"
# prepends the new path in the shell configuration
echo ". /root/miniconda3/etc/profile.d/conda.sh" >> ~/.bashrc
echo "conda activate" >> ~/.bashrc
# INSTALLING PYTHON LIBRARIES
# More packages can/must be added
# depending on the use case.
conda update -y conda # updates conda if required
conda create -y -n py4fi python=3.7 # creates an environment
source activate py4fi # activates the new environment
conda install -y jupyter # interactive data analytics in the browser
conda install -y pytables # wrapper for HDF5 binary storage
conda install -y pandas # data analysis package
conda install -y matplotlib # standard plotting library
conda install -y scikit-learn # machine learning library
conda install -y openpyxl # library for Excel interaction
conda install -y pyyaml # library to manage YAML files
pip install --upgrade pip # upgrades the package manager
pip install cufflinks # combining plotly with pandas
# COPYING FILES AND CREATING DIRECTORIES
mkdir /root/.jupyter
mv /root/jupyter_notebook_config.py /root/.jupyter/
mv /root/cert.* /root/.jupyter
mkdir /root/notebook
cd /root/notebook
# STARTING JUPYTER NOTEBOOK
jupyter notebook --allow-root
# STARTING JUPYTER NOTEBOOK
# as background process:
# jupyter notebook --allow-root &
這個腳本必須複製到Droplet,並由下一小節介紹的編配腳本啓動。
2.4.3 協調Droplet設置的腳本
設置Droplet的第二個bash腳本最短(例2-5)。它主要的作用是將所有其他文件複製到Droplet中,Droplet的IP地址是腳本的一個參數。腳本的最後一行用於啓動install.sh腳本,後者安裝完成後啓動Jupyter Notebook服務器。
例2-5 設置Droplet的bash腳本
#!/bin/bash
#
# Setting up a DigitalOcean Droplet
# with Basic Python Stack
# and Jupyter Notebook
#
# Python for Finance, 2nd ed.
# (c) Dr Yves J Hilpisch
#
# IP ADDRESS FROM PARAMETER
MASTER_IP=$1
# COPYING THE FILES
scp install.sh root@${MASTER_IP}:
scp cert.* jupyter_notebook_config.py root@${MASTER_IP}:
# EXECUTING THE INSTALLATION SCRIPT
ssh root@${MASTER_IP} bash /root/install.sh
現在,設置代碼的所有條件都已經具備。在DigitalOcean上,用如下選項創建一個新的Droplet。
操作系統
Ubuntu 18.10 x64(本書寫作時最新的版本)。
大小
1個內核、1GB內存、25GB SSD(最小的Droplet)。
數據中心所在地區
法蘭克福(因爲作者住在德國)。
SSH密鑰
添加一個(新)SSH密鑰,用於無密碼登錄。[11]
Droplet名稱
您可以使用預先指定的名稱,或者選擇py4fi
等名稱。
單擊Create(創建)按鈕啓動Droplet創建過程,該過程通常需要花費一分鐘。設置過程的主要結果是一個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協議):
https://46.101.156.199:8888
服務器可能要求您添加一個安全例外,添加後應該會出現Jupyter Notebook登錄屏幕,提示輸入密碼(我們的例子中是jupyter)。現在,您已經做好準備,在瀏覽器中通過Jupyter Notebook、通過終端窗口中的IPython或者文本文件編輯器開始Python開發。其他文件管理功能(如文件上傳、刪除和文件夾創建)也已經具備。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-epgGBANU-1582770738685)(/api/storage/getbykey/screenshow?key=18013c684ffc590e9219)]
雲的好處
DigitalOcean等公司提供的雲實例和Jupyter Notebook組合起來很強大,使Python開發人員和“寬客”可以使用專業的計算和存儲基礎設施。專業的雲和數據中心提供商確保您的(虛擬)機器的物理安全和高可用性。使用雲實例還可以將研究和開發階段的成本保持在較低的水平,因爲收費通常按照使用的小時數計算,不需要簽訂長期的協議。
2.5 結語
Python是本書選用的編程語言和技術平臺,並且它被幾乎所有領先的金融機構採用。不過,Python開發可能很難,有時候甚至是乏味且令人頭疼的。幸運的是,近年來已經出現了許多協助解決部署問題的技術。開源項目conda可以幫助管理Python軟件包和虛擬環境。Docker容器更進一步,可以輕鬆地在技術上隔離的“沙箱”(容器)中創建完整的文件系統和運行時環境。DigitalOcean等雲提供商更能在幾分鐘之內,提供專業管理的安全數據中心內的計算及存儲能力,按照小時收費。這些技術與Python 3.7安裝和安全的Jupyter Notebook服務器安裝相結合,爲Python金融項目的開發和部署提供了專業化的環境。
2.6 延伸閱讀
Python軟件包管理可以參考如下資源:
- pip包管理器主頁;
- conda包管理器主頁;
- Python安裝軟件包頁面。
虛擬環境管理可以參考如下資源:
- virtualenv環境管理器頁面;
- conda環境管理頁面;
- 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是管理Jupyter Notebook服務器的多個用戶的一箇中心。
通過推薦人的鏈接註冊DigetalOcean,並在新賬戶中得到10美元的起始餘額。這可以支付最小Droplet兩個月的使用費。
[1] 本版基於CPython 3.7(寫作時最新的主版本),這是Python編程語言最受歡迎的原創版本。——原注
[2] 最新的pipenv項目結合了包管理器pip和虛擬環境管理器virtualenv的功能。——原注
[3] Miniconda安裝程序通常不像conda和Python那樣經常更新。——原注
[4] 安裝元軟件包nomkl(例如使用命令conda install numpy nomkl
),可以避免自動安裝和使用mkl及其他相關軟件包。——原注
[5] 在Python的官方文檔中,可以找到如下解釋:“Python‘虛擬環境’允許Python軟件包安裝於特定應用的獨立位置中,而不是全局安裝。”——原注
[6] Docker技術的全面介紹參見Matthias and Kane(2015)。——原注
[7] 如果對這個術語的理解還不夠清晰,不用擔心,第6章將做進一步介紹。——原注
[8] Consult Robbins (2016)對bash腳本做了簡潔的介紹和概述。——原注
[9] 通過推薦鏈接註冊的新用戶可以得到Digital Ocean的10美元信用額度。——原注
[10] 如果使用自生成證書,您可能需要在瀏覽器提示時添加一個安全例外。——原注
[11] 如果需要幫助,訪問“How to Add SSH Keys to Droplets”或者“How to Create SSH Keys with PuTTY on Windows”網頁。——原注