上週Perfect又推出了新一輪服務器端Swift加強函數庫:Perfect-Python。對,你沒看錯,在服務器端Swift 其實能夠輕鬆從其餘語種的函數庫中直接拿來調用,不須要修改任何內容。若是沒有相似經驗的童鞋能夠參考拙做:
(1)CSwift:https://github.com/RockfordWe... ,
——如何在Swift程序中直接嵌入C語言源代碼
(2)csweet:https://github.com/RockfordWe...,
——如何在Swift程序中直接嵌入C++語言源代碼
(週末剛作的,文檔還沒來得及寫呢,湊合看源代碼吧哈)python
而Perfect-Python不是簡單嵌入源代碼的問題,是容許用戶直接調用Python函數庫自己!!!!git
爲何花大力氣作這些東西?很簡單,程序員都是很懶的傢伙,與其從新把幾萬行代碼重寫一遍,不如直接抓壯丁來的快——現成成熟的代碼在快速原型法中起的做用之大不可思議。程序員
不錯,是由一些很矯情的傢伙宣稱什麼「語言的純潔性」,好比Vapor,去年一直號稱要「純潔的Swift」,結果兩週前終於頂不住壓力,參考上一期Ryan的報告能夠看到:github
Vapor is no longer pure Swift as of Vapor 2, and includes at least chttp and LibreSSL / OpenSSL.swift
翻譯「Vapor已經不像Vapor 2那樣使用純Swift語言了,由於至少包括了一 個C語言組件chttp和LibreSSL / OpenSSL加密函數庫」數組
看見了嗎?Vapor做爲典型的反面教材,在陷入服務器性能問題的泥潭後終於招架不住投降了——用了兩年時間證實一個光鮮的口號是錯誤的,這是什麼樣的代價!「實踐是檢驗真理的惟一標準」——閉門思過去吧。服務器
實踐證實,全棧開發須要揚長避短,而後用統一的一種編譯型語言作主調是在性能和效率上達到最合理平衡點的,目的是:微信
快速開發項目python2.7
維持代碼穩定性函數
項目人工最小化
最短學習曲線
保持組件最新
高性能服務器
迅速增長更多新功能——這是最關鍵最關鍵的
好了,言歸正傳,咱們看一下Perfect-Python的具體用法:
本項目提供了在Swift服務器應用上直接引用Python 2.7函數庫的簡便方法。
本項目採用Swift Package Manager 軟件包管理器編譯,是Perfect 項目的一部分,可是也能夠獨立運行
在使用以前請準備好最新的Swift 3.1 / 4.0 工具鏈
首先請確保 libpython2.7-dev 已經在 Ubuntu 16.04 上正確安裝:
$ sudo apt-get install libpython2.7-dev
請肯定 Xcode 8.3.3 / 9.0 以上版本已經正確安裝
首先在Package.swift中增長依存關係:
.Package(url: "https://github.com/PerfectlySoft/Perfect-Python.git", majorVersion: 1)
而後將下列頭文件導入Swift源代碼:
import PythonAPI import PerfectPython
請注意在任何程序調用以前,必須調用Py_Initialize()
函數初始化python嵌入環境:
Py_Initialize()
使用 PyObj
類對象用於導入python模塊。下列參考範例中,一個名爲/tmp/clstest.py
的腳本被動態導入到當前Swift運行環境:
let pymod = try PyObj(path: "/tmp", import: "clstest")
導入模塊後,您可使用PyObj.load()
函數加載任何一個變量;也能夠反過來用 PyObj.save()
命令保存當前變量爲一個新的值。
好比,如下python腳本中有個叫作 stringVar
的字符串變量:
stringVar = 'Hello, world'
那麼要取得這個字符串的值只須要這樣作:
if let str = pymod.load("stringVar")?.value as? String { print(str) // 會打印變量的字符串值 "Hello, world!" }
此時您還能夠爲該變量直接寫入新的字符串值:
try pymod.save("stringVar", newValue: "Hola!")
注意 目前,Perfect-Python僅支持以下Swift / Python數據類型自動轉換:
Python 類型 | Swift 類型 | 備註 |
---|---|---|
int | Int | |
float | Double | |
str | String | |
list | [Any] | 遞歸轉換 |
dict | [String:Any] | 遞歸轉換 |
好比,您能夠把一個字符串 String
轉換爲 PyObj
,經過 let pystr = "Hello".python()
或者 let pystr = try PyObj(value:"Hello")
完成轉換。
反過來,若是要把 PyObj
類轉換爲Swift數據類型,好比字符串,則仍然有兩種方法:let str = pystr.value as? String
和 let str = String(python: pystr)
。
方法 PyObj.call()
用於帶參數執行某個python函數。以以下python腳本爲例:
def mymul(num1, num2): return num1 * num2
Perfect-Python 能夠用下列方法封裝並調用以上函數,您所須要注意的僅僅是其函數名稱以及參數。其中函數名稱用字符串代替,而參數用一個數組表達:
if let res = pymod.call("mymul", args: [2,3])?.value as? Int { print(res) // 結果爲 6 }
請一樣使用 PyObj.load()
函數用於家在Python類對象,可是注意後面必定要緊跟一個PyObj.construct()
用於初始化類對象實例。該方法一樣支持用一個任意類型的數組做爲參數進行對象構造。
假設以下腳本的典型python類對象 Person
,該類有兩個屬性姓名name
和年齡age
,還有一個名爲「自我介紹」的類對象方法intro()
:
class Person: def __init__(self, name, age): self.name = name self.age = age def intro(self): return 'Name: ' + self.name + ', Age: ' + str(self.age)
在Swift中初始化上述類對象的方法須要進行如下兩步走:
if let personClass = pymod.load("Person"), let person = personClass.construct(["rocky", 24]) { // person is now the object instance }
以後就能夠訪問類實例的屬性變量和方法了,如同上文所提到的普通變量和函數調用的方法同樣:
if let name = person.load("name")?.value as? String, let age = person.load("age")?.value as? Int, let intro = person.call("intro", args: [])?.value as? String { print(name, age, intro) }
參考如下python代碼,此時若是執行 x = caller('Hello', callback)
則能夠將函數做爲參數進行回調:
def callback(msg): return 'callback: ' + msg def caller(info, func): return func(info)
在Swift中等效的代碼平淡無奇,只不過將待調函數做爲參數而已::
if let fun = pymod.load("callback"), let result = pymod.call("caller", args: ["Hello", fun]), let v = result.value as? String { print(v) // 結果是 "callback: Hello" }
關於本項目更多內容,請參考perfect.org.