上周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.