phpy 是识沃团队最新推出的开源项目,目标是为 php 引入 python 生态,来弥补 php 生态的空缺和不足。phpy 使得 php 可以调用所有 python 的包。 包括当下非常流行的 pytorch、transformers、tensorflow 等 ai 库,以及 numpy、pandas、scikit 等科学计算库,还可以使用 pyqt、wxpython 等图形界面库。
不建议在 php-fpm/apache 短生命周期运行环境下使用,频繁地导入 / 销毁模块的开销会消耗大量资源
编译安装
phpy 可以作为 php 的扩展,也可以作为 python 的 c 模块。既可以在 php 代码中调用 python 的库,也可以在 python 中调用 php 的类和函数。
作为 python 模块时依赖 php 的 embed sapi ,检查 php 的目录中,确保存在 libphp.so
ll /opt/php-8.1/lib/libphp.so-rwxr-xr-x 1 htf htf 39397224 11月 30 19:25 /opt/php-8.1/lib/libphp.so*
编译依赖
python 3.10 或以上版本,建议使用 conda 工具来安装
php 8.1 或以上版本
python 将安装到 /opt/anaconda3 目录下
/opt/anaconda3/bin/pythonpython 主程序
/opt/anaconda3/include/python3.11 头文件
/opt/anaconda3/lib/python3.11 动态链接库目录
另外需要配置 /etc/ld.so.conf.d/conda.conf 加入 /opt/anaconda3/lib 和 /opt/php-8.1/lib 。执行 ldconfig 检查是否可以找到 libpython3.11.so 和 libphp.so。
sudo ldconfig -p |grep php libphp7.so (libc6,x86-64) => /opt/php-7.4/lib/libphp7.so libphp.so (libc6,x86-64) => /opt/php-8.0/lib/libphp.so sudo ldconfig -p |grep python libsamba-policy.cpython-38-x86-64-linux-gnu.so.0 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libsamba-policy.cpython-38-x86-64-linux-gnu.so.0 libpython3.11.so.1.0 (libc6,x86-64) => /opt/anaconda3/lib/libpython3.11.so.1.0 libpython3.11.so (libc6,x86-64) => /opt/anaconda3/lib/libpython3.11.so libpython3.8.so.1.0 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libpython3.8.so.1.0 libpython3.8.so (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libpython3.8.so libpython3.5m.so.1.0 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libpython3.5m.so.1.0 libpython3.so (libc6,x86-64) => /opt/anaconda3/lib/libpython3.so libpython2.7.so.1.0 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0 libpython2.7.so (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libpython2.7.so
作为 php 扩展
检查 config.m4 中 python 路径是否正确。若 python 的安装路径不是 /opt/anaconda3,需修改为正确的安装路径。
cd phpyphpize./configuremake install
安装成功后,修改 php.ini ,加入 extension=phpy.so,执行 php -m 和 php --ri phpy 检查是否成功加载扩展。
作为 python 模块
cmake .make -j执行成功后,会生成 tests/lib/phpy.so 文件。可以在 python 中直接导入此模块。import phpy
使用方法
导入 python 模块
$os = pycore::import('os');
执行函数
$uname = $os->uname();
读取属性
echo $uname->sysname;
加载路径
可使用 pycore::import('sys')->path->append() 将一些目录加入到加载路径列表中。
例如:/workspace/app/user.py 自定义的包,可以通过下面的步骤实现加载:
pycore::import('sys')->path->append('/workspace') 将 /workspace 添加到 sys.path 中
pycore::import('app.user') 将自动搜索 sys.path 找到对应的 app/user.py 包并载入
内置方法
pycore::str() 将对象转为字符串
pycore::repr()
pycore::type() 获取对象的类型
pycore::locals() 获取当前空间内容的所有局部变量
pycore::globals() 获取所有全局变量
pycore::hash() 获取 hash 值
pycore::hasattr() 检测对象是否存在某个属性
pycore::id() 获取对象的内部编号
pycore::len() 获取长度
pycore::dir() 获取对象所有的属性、方法
pycore::int() 构造一个整数
pycore::float() 构造一个浮点数
pycore::fn() 构造一个可调用函数
pycore::scalar() 将 pyobject 对象转为 php 的标量类型,例如 pystr 将转为 php 字符串,dict/tuple/set/list 将转为 array
内置类
pyobject:所有其他类型的基类
pydict:字典类型,等同于 php 的关联数组
pylist:列表类型,等同于 php 的索引数组
pytuple:元组,不可变的列表
pystr:字符串
pymodule:python 包,pymodule 也是 pyobject 的子类
pyobject 是除了 pycore 之外,所有其他类型的基类。非内置类的对象是 pyobject 的实例。pyobject 实现了 4 个魔术方法,用于将操作映射到 python 对象。 所有类方法、参数、返回值参考 stubs 目录中的文件。
继承关系
pyobject -> pymodule -> pysequenece -> pylist -> pytuple -> pyset -> pystr -> pydict -> pytype
整数
python 语言是天然支持无限精度整型计算的,可以使用 python 的整数计算能力来代替 ext-bcmath
构造
使用 pycore::int() 函数来构造一个数字,可以传入整数、浮点数、字符串来初始化。
$i1 = pycore::int(12345678);$i2 = pycore::int('1234567890123456789012345678901234567890');$i3 = pycore::int(12345678.03);
运算
整数同样也是 pyobject 的实例,可以使用内置的方法类实现运算。
$i = pycore::int(12345435);var_dump(strval($i->__pow__(3)));var_dump(strval($i->__add__(4)));将输出 1881564851360655187875 ,由于超过了 64位 最大精度,因此输出结果将自动转为字符串类型。
命名参数
phpy 支持了命名参数,可以使用命名参数来调用 python 的函数和方法。 顺序参数必须在前,命名参数必须在最后
kwargs($a, $b, $c, name: 'hello', world: 'rango');对应的 python 代码为:kwargs(a, b, c, name: 'hello', world: 'rango')
回调函数
可将 php 的可调用对象作为 python 的回调函数。使用 pycore::fn(callable $fn) 包裹即可。
$m = pycore::import('app.user');$uuid = uniqid();$rs = $m->test_callback(pycore::fn(function ($namespace) use ($uuid) { var_dump($namespace); return $uuid;}));
import app.user 导入了一个自定义 python 包
调用了包中的一个函数 test_callback,此函数接受一个参数为 python callable 对象
使用 pycore::fn() 包裹了一个 closure 闭包对象作为回调,这里也支持函数名称字符串、对象方法的调用方式
回调函数返回了一个字符串,在 test_callback 函数中会得到一个 str 类型返回值
可参考下方的 python tkinter 例子。
实际案例
基于 tkinter 实现 gui 的例子
tk();$root->title('我的窗口');$root->geometry(500x500);$root->resizable(false, false);$button= $tkinter->button($root, text: click me!!, command: pycore::fn(function () { var_dump(func_get_args()); echo 'click me!!'. php_eol;}));$button->pack();$tkinter->mainloop();
一个基于 transformers 的情感分析模型推理实现
environ->__setitem__('https_proxy', getenv('https_proxy'));$distilled_student_sentiment_classifier= $transformers->pipeline( model: lxyuan/distilbert-base-multilingual-cased-sentiments-student, top_k: null,);$rs= $distilled_student_sentiment_classifier(i love this movie and i would watch it again and again!);var_dump(pycore::scalar($rs));
音频放大电路图锦集
12V/24V转正负150V/200V/300V双路控制可调模块电源
区块链对于公司而言会有什么影响
网格环境微型监测系统的主要功能有哪些?
Beats Studio 3 评测解析
phpy:PHP与Python互调用库
智慧供水整体解决方案 打造数字孪生智慧供水解决方案
复工企业借UWB技术实现防控疫情智慧化管理
基于Arduino的低功耗睡眠模式设计方案
国产时钟IC-AiP8563替代AT8563/HYM8563/PCF8563,主要运用在RK方案上面
三通道低功耗ASK低频唤醒接收器简介
svpwm与动量轮怎么融合 svpwm变频调速原理
景区扬尘在线监测设备功能
便携式口罩呼吸机的设计特点是什么
彩灯控制器电路图大全
罗姆发布肖特基二极管白皮书,助力汽车、工业和消费电子设备实现小型化和更低损耗!
腾讯动真格做自动驾驶?招聘行动已经开始
珠联璧合:NVIDIA与VMware联合发布AI就绪型企业级平台
如何配置降压转换器实现多输出
二阶数字陷波器的设计方法及数字传输函数