PostgreSQL PL/Python: 在虚拟环境中调用存储过程

3
当我在Python应用程序中调用一个PostgreSQL PL/Python存储过程时,它似乎在以用户postgres运行的单独进程中执行。到目前为止,这只有一个副作用,即我必须使我的日志文件可写,供我自己和数据库用户使用,因此应用程序和存储过程都可以向其写入。
然而,现在我开始使用virtualenv并添加了一些.pth文件到~/.virtualenvs/virt_env/lib/python2.7/site-packages/文件夹中,将路径添加到我的模块路径中。
当执行存储过程时,用户postgres不在与我相同的虚拟环境中,因此存储过程找不到我的模块。我可以在全局PostgreSQL环境中修改PYTHONPATH,但每次切换虚拟环境时我都必须更改它——这有点违反了virtualenv的目的……
我该如何扩展存储过程的Python路径?
更新:已经有一个类似的问题被提出,解决方法是修改Postgres中的PYTHONPATH环境变量;然而,似乎没有标准的方法来指定PostgreSQL的环境变量,至少在Mac OSX上不是可行的解决方案。
2个回答

3
自1.6版本左右开始,虚拟环境(virtualenv)提供了一种方法。有一个名为activate_this.py的脚本,可以用来设置现有解释器以访问特定的虚拟环境。请注意保留HTML标记。
exec(open('/Some/VirtualEnv/Directory/myvirtualenv/bin/activate_this.py').read(), 
dict(__file__='/Some/VirtualEnv/Directory/myvirtualenv/bin/activate_this.py'))

而作为一个完全实现的 plpython 函数:

CREATE OR REPLACE FUNCTION workon(venv text)
  RETURNS void AS
$BODY$
    import os
    import sys

    if sys.platform in ('win32', 'win64', 'cygwin'):
        activate_this = os.path.join(venv, 'Scripts', 'activate_this.py')
    else:
        if not os.environ.has_key('PATH'):
            import subprocess
            p=subprocess.Popen('echo -n $PATH', stdout=subprocess.PIPE, shell=True)
            (mypath,err) = p.communicate()
            os.environ['PATH'] = mypath

        activate_this = os.path.join(venv, 'bin', 'activate_this.py')

    exec(open(activate_this).read(), dict(__file__=activate_this))
$BODY$
LANGUAGE plpythonu VOLATILE

由于默认情况下在plpython os.environ中不可用,因此需要额外的PATH修改 - activate_this.py有一个修复已检入,应该随着下一个点版本发布(应该是1.11.7或1.12)

(主要取自https://gist.github.com/dmckeone/69334e2d8b27f586414a


我不确定这个virtualenv路径是否在多个plpython调用中保持活动状态,因为解释器在每次调用时都是新的。我想你假设我们从所有plpython方法的开头调用workon()? - Sid
实际上,在一个会话(数据库连接)中,所有的plpython函数共享一个解释器,尽管它们会获得一个新的执行状态(除了全局GD数据共享字典)——你不需要为每个查询启动一个新的解释器。不要多次调用它,否则sys.path将继续增长。 - reedstrm

2
通常我会说这不是一个好主意,但你可以尝试参考这个问题
你可以运行多个 PostgreSQL 实例,每个实例使用不同的环境来允许各种不同的 PYTHONPATH 设置。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接