侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

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

php  /  管理员 发布于 1年前   403

phpy 是识沃团队最新推出的开源项目,目标是为 PHP 引入 Python 生态,

来弥补 PHP 生态的空缺和不足。phpy 使得 PHP 可以调用所有 Python 的包。

包括当下非常流行的 PyTorch、transformers、TensorFlow 等 AI 库,

以及 Numpy、Pandas、Scikit 等科学计算库,还可以使用 PyQt、wxPython 等图形界面库。

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 phpy
phpize
./configure
make 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 的例子

<?php
$tkinter = PyCore::import('tkinter');
$root = $tkinter->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();

1.png


一个基于 transformers 的情感分析模型推理实现

<?php
$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_k: null,
);
$rs = $distilled_student_sentiment_classifier ("I love this movie and i would watch it again and again!");
var_dump(PyCore::scalar($rs));

2.png



  • 上一条:
    在laravel10+框架中使用vant4实现多个单页面路由
    下一条:
    在go语言中将日期或时间戳从字符串转换为time.Time类型示例
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • 用Time Warden监控PHP中的代码处理时间(0个评论)
    • 在PHP中使用array_pop + yield实现读取超大型目录功能示例(0个评论)
    • Property Hooks RFC在PHP 8.4中越来越接近现实(0个评论)
    • 近期文章
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • Laravel 11.15版本发布 - Eloquent Builder中添加的泛型(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-06
    • 2017-07
    • 2017-08
    • 2017-09
    • 2017-11
    • 2017-12
    • 2018-01
    • 2018-02
    • 2018-03
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-09
    • 2021-02
    • 2021-03
    • 2021-04
    • 2021-05
    • 2021-06
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2021-12
    • 2022-01
    • 2022-02
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-08
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    • 2024-05
    • 2024-06
    • 2024-07
    • 2024-09
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客