天天看點

函數計算 Python 連接配接 SQL Server 小結

python 連接配接資料庫通常要安裝第三方子產品,連接配接 MS SQL Server 需要安裝 pymssql 。由于 pymsql 依賴于 FreeTDS

,對于先于 2.1.3 版本的 pymssql,需要先安裝 FreeTDS。由于早期版本的 pymssql 隻提供了 windows 下的 wheel 打包,其他平台(如 linux)需要從源碼包編譯安裝,那需要先安裝 freetds-dev 包,以提供必要的頭檔案。

函數計算的 runtime 運作時的目錄是隻讀的,是以對于需要使用 apt-get 和 pip 安裝依賴的場景,需要将依賴安裝在代碼目錄而不是系統目錄。具體安裝方法可以參考

《函數計算安裝依賴庫方法小結》

。而 pymssql 的老版本涉及到編譯安裝,比常見的二級制安裝到本地目錄略複雜一些。

函數計算依賴安裝需要有個模拟的 linux 環境,從前我們推薦使用 fcli shell 的 sbox ,啟動一個接近生産環境的 docker container 進行依賴安裝。因為有些依賴是平台相關的,在 mac 系統安裝的動态連結庫無法在函數計算的 linux 環境下運作, pymssql 恰好屬于這種情況。本文我将使用

fc-docker

進行安裝和本地測試。

下面的例子是基于函數計算 runtime python3.6 的,對于 python2.7 也進行了測試,同樣适用。

準備測試環境

首先使用 docker 在本機 Mac 電腦下運作一個 SQL Server 2017 服務,并初始化表結構,編輯一個 index.py 的測試檔案,以驗證資料庫通路是否成功。

$ docker pull mcr.microsoft.com/mssql/server:2017-latest

$ docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=Codelife.me' \
   -p 1433:1433 --name sql1 \
   -d mcr.microsoft.com/mssql/server:2017-latest           

将 SQL Server 啟動于 1433 端口,并設定 SA 賬戶密碼為

Codelife.me

$ brew tap microsoft/mssql-release https://github.com/Microsoft/homebrew-mssql-release
$ brew update
$ ACCEPT_EULA=y brew install --no-sandbox msodbcsql mssql-tools           

使用 homebrew 安裝 mssql 用戶端 sqlcmd。

$ sqlcmd -S localhost -U SA -P 'Codelife.me'
1>CREATE DATABASE TestDB
2>SELECT Name from sys.Databases
3>GO
Name
-----------------------------------------------
master
tempdb
model
msdb
TestDB

(5 rows affected)           

建立測試資料庫 TestDB。

1> USE TestDB
2> CREATE TABLE Inventory (id INT, name NVARCHAR(50), quantity INT)
3> INSERT INTO Inventory VALUES (1, 'banana', 150); INSERT INTO Inventory VALUES (2, 'orange', 154);
4> GO
Changed database context to 'TestDB'.

(1 rows affected)

(1 rows affected)           

建立一張 Inventory 表,并參入一行測試資料。

1> SELECT * FROM Inventory WHERE quantity > 152;
2> GO
id          name                                               quantity
----------- -------------------------------------------------- -----------
          2 orange                                                     154

(1 rows affected)
1> QUIT           

驗證一下插入結果并退出。

準備一個測試函數

import pymssql

def handler(event, context):
    conn = pymssql.connect(
        host=r'docker.for.mac.host.internal',
        user=r'SA',
        password=r'Codelife.me',
        database='TestDB'
    )
    
    cursor = conn.cursor()
    cursor.execute('SELECT * FROM inventory WHERE quantity > 152')
    
    result = ''

    for row in cursor:
        result += 'row = %r\n' % (row,)

    conn.close()
    return result           

編寫一個測試函數 index.py。該函數連接配接 mac 主控端

docker.for.mac.host.internal

(這裡不能是 localhost,因為 fc-docker 會将函數運作在 container 内部)的 SQL Server 服務。執行一個查詢,并把結果傳回出來。

最新版的 pymssql

建立一個空目錄,存放上 index.py 檔案。将指令會話的目前路徑切換到 index.py 所在的目錄,然後執行

$ docker run --rm --name mssql-builder -t -d -v $(pwd):/code --entrypoint /bin/sh aliyunfc/runtime-python3.6
$ docker exec -t mssql-builder pip install -t /code pymssql
$ docker stop mssql-builder           
  1. 這裡使用了 fc-docker 提供的 python3.6 的模拟環境:aliyunfc/runtime-python3.6
  2. 第一行啟動了一個不會退出的 docker container,第二行使用 docker exec 進入這個 container 安裝依賴,最後一行退出該 container。因為本地路徑 $(pwd) 被挂載到 container 内部的 /code 目錄,是以 container 退出以後 /code 目錄的内容還會保留在本地目前路徑下。
  3. pip 通過 -t 參數将 wheel 包安裝在 /code 目錄下。
$ docker run --rm -v $(pwd):/code aliyunfc/runtime-python3.6 --handler index.handler
row = (2, 'orange', 154)


RequestId: d66496e9-4056-492b-98d9-5bf51e448174          Billed Duration: 144 ms         Memory Size: 19           

執行上面指令可以順利傳回結果。對于不需要使用老本 pymssql 的使用者看到這裡就可以結束了。

早期版本的 pymssql

對于早于 2.1.3 版本的 pymssql, pip install 會觸發源碼編譯安裝,對于這種情況,需要安裝編譯時依賴的 freetds-dev,以及運作時依賴的 libsybdb5。編譯時依賴可以直接安裝在系統目錄裡,運作時依賴必須安裝在本地目錄下。

docker run --rm --name mssql-builder -t -d -v $(pwd):/code --entrypoint /bin/sh aliyunfc/runtime-python3.6

docker exec -t mssql-builder apt-get install -y -d -o=dir::cache=/code libsybdb5
docker exec -t mssql-builder bash -c 'for f in $(ls /code/archives/*.deb); do dpkg -x $f $(pwd) ; done;'
docker exec -t mssql-builder bash -c "rm -rf /code/archives/; mkdir /code/lib;cd /code/lib; ln -sf ../usr/lib/x86_64-linux-gnu/libsybdb.so.5 ."
docker exec -t mssql-builder apt-get install -y freetds-dev 
docker exec -t mssql-builder pip install cython 
docker exec -t mssql-builder pip install -t /code pymssql==2.1.3

docker stop mssql-builder           
  1. 第一行啟動一個 container,第十行停止并自動删除該 container。
  2. 第二行至第三行将運作時依賴 libsybdb5 安裝于本地目錄。
  3. 将動态連結庫 libsybdb.so.5 連結到目錄 /code/lib 目錄下,因為該目錄預設配置到了環境變量 LD_LIBRARY_PATH 下。
  4. 将 freetds-dev 和 cython 安裝到系統目錄,用于 pymssql 編譯安裝,因為運作時 pymssql 不需要這兩個庫,是以無需安裝在本地目錄
  5. 安裝 2.1.3 版本的 pymssql,從 2.1.4 版本開始已經不需要源碼安裝了。
$ docker run --rm -v $(pwd):/code aliyunfc/runtime-python3.6 --handler index.handler
row = (2, 'orange', 154)


RequestId: d66496e9-4056-492b-98d9-5bf51e448174          Billed Duration: 144 ms         Memory Size: 19           

測試通過。

小結

這是一份來遲的函數計算使用 sql server 資料庫的配置文檔。目前版本的 pymssql 已經不再需要源碼安裝了。但是 pip 源碼包安裝的方法,對于其他類似的場景也是适用的。

本文也提供了一種基于 fc-docker 的配置和調試方法,不同 fcli 的 sbox,fc-docker 可以寫成腳本反複執行,并且也可以用于本地模拟執行,對于 CI 場景非常有幫助。

參考閱讀

  1. http://www.pymssql.org/en/latest/intro.html#install
  2. http://www.freetds.org/
  3. http://www.pymssql.org/en/stable/pymssql_examples.html
  4. https://docs.microsoft.com/en-us/sql/linux/quickstart-install-connect-docker?view=sql-server-2017
  5. https://cloudblogs.microsoft.com/sqlserver/2017/05/16/sql-server-command-line-tools-for-macos-released/