PL/Python是PostgreSQL提供的一种过程语言扩展,允许在数据库内部使用Python编写函数和触发器。它让开发者可以利用Python丰富的标准库和第三方库直接处理数据逻辑,而无需在应用层反复搬运数据。本文围绕安装、配置和验证三个环节,整理一套可操作的步骤。

一、安装前确认PostgreSQL的编译状态
并非所有PostgreSQL安装包都默认启用PL/Python。从源码编译时如果没有添加对应参数,或者使用裁剪过的发行版二进制包,都可能缺少plpython3扩展。第一步要检查当前服务器是否已经具备PL/Python支持。在Linux环境下可以通过pg_config --configure查看编译参数,确认其中是否包含--with-python。如果该选项存在,说明服务器二进制已经带上了PL/Python模块,后续只需要在目标数据库创建扩展即可。
如果检查结果为空,则需要重新编译或安装包含PL/Python的软件包。以Debian/Ubuntu为例,通常会提供postgresql-contrib或单独的postgresql-plpython3-版本号包。在Red Hat/CentOS系列中,则对应postgresql-plpython3包。Windows平台下的图形化安装器通常已包含PL/Python组件,但仍需在数据库级别手动创建扩展。
pg_config --configure | grep python
除了服务器编译状态,还要确认Python开发头文件是否齐全。编译PL/Python时需要包含Python.h以及对应的共享库。以Ubuntu为例,如果没有安装python3-dev,在源码编译阶段会直接报错,提示找不到Python头文件。因此安装前建议先执行python3-config --includes确认头文件路径,或直接通过包管理器安装开发包。
二、编译安装时启用PL/Python
对于选择源码编译的用户,configure阶段就必须明确加入Python支持。常见的配置命令为./configure --with-python --prefix=/usr/local/pgsql。这里的--with-python会让构建系统检测当前环境中的Python版本,并编译对应的plpython3.so动态库。如果不指定该参数,后续即使执行make world也不会生成PL/Python扩展。
编译完成后需要使用make install-world而不是普通的make install,因为PL/Python作为附加扩展,源码位于contrib目录下,只有install-world才会安装这部分文件。安装完成后可以到PostgreSQL的lib目录确认plpython3.so文件是否存在,在Linux默认安装路径下通常位于/usr/local/pgsql/lib/plpython3.so。
./configure --with-python --prefix=/usr/local/pgsql make world make install-world
需要特别注意Python大版本的匹配关系。PostgreSQL 9.x到11版本中同时存在plpythonu和plpython3u,前者对应Python 2,后者对应Python 3。从PostgreSQL 12开始,Python 2支持被移除,plpythonu不再可用,统一使用plpython3u。如果系统同时安装了Python 2和Python 3,configure时可以通过PYTHON环境变量指定使用哪个Python可执行文件,避免扩展绑定到错误的解释器。
三、在数据库中创建扩展与权限配置
服务器安装完成后,PL/Python并不会自动出现在每个数据库中。需要以超级用户身份连接目标数据库,执行CREATE EXTENSION语句。扩展名固定为plpython3u,其中末尾的u表示untrusted language,即不受信任语言。这类语言编写的函数可以访问文件系统、调用外部命令,因此只有超级用户才有权限创建扩展。
CREATE EXTENSION IF NOT EXISTS plpython3u;
创建扩展之后,普通用户还不能直接使用PL/Python编写函数。需要超级用户显式授予该语言的使用权限。例如允许用户developer使用PL/Python语言,可以执行以下语句。
GRANT USAGE ON LANGUAGE plpython3u TO developer;
如果希望所有新建数据库自动拥有PL/Python扩展,可以在模板数据库template1中先执行一次CREATE EXTENSION。这样后续通过CREATE DATABASE创建的数据库都会继承该扩展。但这样做会让所有新库都携带PL/Python能力,需要结合安全策略评估是否合适。对于生产环境,更常见的做法是按需在业务库中逐个创建扩展。
四、验证安装并处理常见问题
完成以上步骤后,可以创建一个简单的PL/Python函数来验证环境是否正常工作。下面的函数返回当前Python解释器的版本信息,如果执行成功说明扩展加载正常,Python环境也能被正确调用。
CREATE OR REPLACE FUNCTION py_version() RETURNS text AS $$ import sys return sys.version $$ LANGUAGE plpython3u;
执行SELECT py_version();时,如果返回类似于3.10.12 (main, Jun 11 2023, 05:26:28) [GCC 11.4.0]的字符串,说明PL/Python已经可以正常工作。如果此时报错could not load library "plpython3.so",往往是PostgreSQL进程找不到Python的动态库。在Linux下可以通过ldconfig更新动态库缓存,或者在启动脚本中设置LD_LIBRARY_PATH。Windows环境则需要确认Python安装目录的DLL路径已加入系统PATH变量。
另一个容易被忽视的问题是第三方模块的导入路径。数据库服务运行在独立的系统用户下,其环境变量与应用开发环境不同。如果函数中引入numpy、requests等第三方模块,而模块安装在虚拟环境或用户目录下,数据库进程可能找不到这些模块。解决办法是在系统级别安装所需模块,或者在函数内部动态修改sys.path。也可以为PostgreSQL服务单独设置PYTHONPATH环境变量,但要注意不同操作系统和启动方式的差异。
import sys sys.path.insert(0, '/opt/plpython/venv/lib/python3.10/site-packages') import numpy as np return np.__version__
由于PL/Python属于不受信任语言,函数执行时拥有与数据库服务进程相同的系统权限。一旦函数内部出现文件删除、网络请求或资源耗尽等操作,可能直接影响整个数据库实例的稳定性。因此建议只允许经过审核的开发人员使用该语言,并避免在共享数据库环境中向陌生人授予USAGE权限。对于需要限制资源使用的场景,可以考虑通过操作系统级别的资源控制来约束PostgreSQL服务的进程组。

