phpy :PHP 与 Python 互调用库,为 PHP 引入 Python 生态,PHP 也可以写 AI 了
source link: https://blog.p2hp.com/archives/11720
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
phpy :PHP 与 Python 互调用库,为 PHP 引入 Python 生态,PHP 也可以写 AI 了
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/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();
一个基于 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));
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK