slot deposit pulsa slot mahjong slot gacor slot gacor slot gacor resmi slot gacor 2025 slot gacor terpercaya slot gacor 2025 slot gacor hari ini slot gacor hari ini slot gacor hari ini
phpy :PHP 与 Python 互调用库,为 PHP 引入 Python 生态,PHP 也可以写 AI 了
17611538698
webmaster@21cto.com

phpy :PHP 与 Python 互调用库,为 PHP 引入 Python 生态,PHP 也可以写 AI 了

编程语言 0 1305 2023-12-05 08:46:12
导读:phpy是国内PHP技术提供商识沃科技新开发的PHP与Pythoon调用库,用来弥补PHP当前生态的空缺与不足。

图片

背景

识沃国内PHP技术提供商,是协程产品Swoole的开发团队。

swoole 的创始人为韩天峰(Rango),为 PHP 官方 PECL 开发组的成员,曾任职于腾讯、阿里巴巴、虎牙直播等,曾为好未来集团的首席架构师,为中国 PHP 领域中除了鸟哥(惠新辰)国外颇具影响力的PHP技术专家。

而 phpy 是识沃团队最新推出的开源项目,目标是为 PHP 引入 Python 生态,来弥补 PHP 生态的空缺和不足。phpy 使得 PHP 可以调用所有 Python 的包。

包括当下非常流行的 PyTorchtransformersTensorFlow 等 AI 库,以及 NumpyPandasScikit 等科学计算库,还可以使用 PyQtwxPython 等图形界面库。

  • GitHub 地址:https://github.com/swoole/phpy

不建议在 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*

编译依赖

  1. Python 3.10 或以上版本,建议使用 conda 工具来安装

  2. PHP 8.1 或以上版本

Python 将安装到 /opt/anaconda3 目录下

  • /opt/anaconda3/bin/python Python 主程序

  • /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 自定义的包,可以通过下面的步骤实现加载:

  1. PyCore::import('sys')->path->append('/workspace') 将 /workspace 添加到 sys.path 中

  2. 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:字符串

  • PyModulePython 包,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 的例子

$tkinter = PyCore::import('tkinter');
$root = $tkinter->Tk();
$root->title('我的窗口');
$root->geometry("500x500");
$root->resizable(False, False);
$button = $tkinter->Button($roottext"Click Me!!"commandPyCore::fn(function () {    var_dump(func_get_args());    echo'click me!!' . PHP_EOL;
}));
$button->pack();
$tkinter->mainloop();

图片

一个基于 transformers 的情感分析模型推理实现。代码如下:

$transformers = PyCore::import('transformers');
$os = PyCore::import('os');
$os->environ->__setitem__('https_proxy'getenv('https_proxy'));
$distilled_student_sentiment_classifier = $transformers->pipeline(    model"lxyuan/distilbert-base-multilingual-cased-sentiments-student",    top_knull,);
$rs = $distilled_student_sentiment_classifier ("I love this movie and i would watch it again and again!");
var_dump(PyCore::scalar($rs));

图片

作者:识沃团队

评论