9

如果可以在 Postgres Python 存储过程或触发器中使用 NLTK,是否有人做过,甚至没有

4

1 回答 1

15

您可以在 PL/Python 存储过程或触发器中使用几乎任何 Python 库。

请参阅PL/Python 文档

概念

要理解的关键点是PL/PythonCPython(无论如何,在 PostgreSQL 直到并包括 9.3);它使用与普通独立 Python 完全相同的解释器,它只是将其作为库加载到支持的 PostgreSQL 中。有一些限制(如下所述),如果它适用于 CPython,它适用于 PL/Python。

如果您的系统上安装了多个 Python 解释器 - 版本、发行版、32 位与 64 位等 - 您可能需要确保在运行 distutils 脚本等时将扩展和库安装到正确的解释器中,但仅此而已关于它。

由于您可以加载系统 Python 可用的任何库,因此没有理由认为 NLTK 会成为问题,除非您知道它需要诸如线程之类的东西,而 PostgreSQL 后端并不真正推荐它。(果然,我试过了,它“刚刚好”,见下文)。

一个可能的担忧是,像 NLTK 之类的启动开销可能非常大,您可能希望在 postmaster 中预加载 PL/Python 并在设置代码中导入模块,以便在后端启动时准备好。了解 postmaster 是所有其他后端的父进程fork(),因此如果 postmaster 预加载某些内容,则后端可以使用它,从而大大减少开销。无论哪种方式都可以测试性能。

安全

因为您可以通过 PL/Python 加载任意 C 库,并且因为 Python 解释器没有真正的安全模型,plpythonu所以它是一种“不受信任”的语言。脚本作为用户可以完全且不受限制地访问系统,postgres并且可以相当简单地绕过 PostgreSQL 中的访问控制。出于明显的安全原因,这意味着 PL/Python 函数和触发器只能由超级用户创建,尽管对于GRANT普通用户来说,运行由超级用户安装的精心编写的函数是相当合理的。

好处是您几乎可以在普通 Python 中做任何事情,请记住 Python 解释器的生命周期是数据库连接(会话)的生命周期。不建议使用线程,但大多数其他事情都很好。

PL/Python 函数必须在编写时仔细输入卫生,search_path在调用 SPI 以运行查询时必须设置,等等。这在手册中有更多讨论。

限制

长时间运行或可能有问题的事情,如 DNS 查找、与远程系统的 HTTP 连接、SMTP 邮件传递等,通常应使用帮助脚本LISTENNOTIFY不是后端作业来完成,以保持 PostgreSQL 的性能并避免VACUUM大量阻碍的长交易。你可以在后端做这些事情,这不是一个好主意。

您应该避免在 PostgreSQL 后端创建线程。

不要尝试加载任何会加载libpqC 库的 Python 库。这可能会导致后端出现各种令人兴奋的问题。从 PL/Python 与 PostgreSQL 对话时,使用 SPI 例程而不是常规客户端库。

不要在后端做很长时间运行的事情,你会导致真空问题。

不要加载任何可能加载已加载的本机 C 库的不同版本的任何内容——比如不同的 libcrypto、libssl 等。

永远不要直接写入 PostgreSQL 数据目录中的文件。

PL/Python 函数postgres在操作系统上以系统用户身份运行,因此它们无权访问用户的主目录或连接客户端上的文件等内容。

测试结果

$ yum install python-nltk python-nltk
$ psql -U postgres regress

regress=# CREATE LANGUAGE plpythonu;

regress=# CREATE OR REPLACE FUNCTION nltk_word_tokenize(word text) RETURNS text[] AS $$
          import nltk
          return nltk.word_tokenize(word)
          $$ LANGUAGE plpythonu;

regress=# SELECT nltk_word_tokenize('This is a test, it''s going to work fine');
              nltk_word_tokenize               
-----------------------------------------------
 {This,is,a,test,",",it,'s,going,to,work,fine}
(1 row)

所以,正如我所说:试试吧。只要 PostgreSQL 用于 plpython 的 Python 解释器安装了 nltk 的依赖项,它就可以正常工作。

笔记

PL/Python 是 CPython,但我希望看到一个基于 PyPy 的替代方案,它可以使用 PyPy 的沙盒功能运行不受信任的代码。

于 2013-04-29T11:50:06.603 回答