【问题标题】:How are import statements in plpython handled?plpython 中的 import 语句是如何处理的?
【发布时间】:2013-02-08 00:08:36
【问题描述】:

我有一个 plypython 函数,它可以做一些 json 魔术。为此,它显然导入了 json 库。

每次调用函数时都会调用导入吗?有什么我必须注意的性能影响吗?

【问题讨论】:

    标签: python json postgresql postgresql-9.1 plpython


    【解决方案1】:

    PL/Python 函数体中的声明最终会变成一个普通的 Python 函数,因此会表现得如此。当 Python 函数第一次导入模块时,模块会缓存在 sys.modules 字典 (https://docs.python.org/3/reference/import.html#the-module-cache) 中。同一模块的后续导入将简单地将导入名称绑定到字典中找到的模块对象。从某种意义上说,我所说的可能会让人怀疑接受的答案中给出的提示的有用性,因为它有点多余,因为 Python 已经为你做了类似的缓存。

    总而言之,我想说的是,如果您以简单使用 importfrom [...] import 构造的标准方式导入,那么您不必担心在函数或其他方式中重复导入,Python 已经你覆盖了。

    另一方面,Python 允许您绕过其原生导入语义并实现自己的(使用__import__() 函数和importlib 模块)。如果您正在这样做,也许您应该查看工具箱中的可用内容 (https://docs.python.org/3/reference/import.html)。

    【讨论】:

    • 这是正确的。如果函数已经被导入到不同的函数中,import 将不会做任何事情。我在围绕 plpython 编写模块时遇到了这个问题。您需要重新启动数据库(进而重新启动解释器)才能重新运行导入。或者像你建议的那样,搞乱 importlib。
    【解决方案2】:

    import 在每个函数调用上执行。如果您在函数体中编写带有 import 语句的普通 Python 模块,与在模块级别相反,这与您将得到的行为相同。

    是的,这会影响性能。

    您可以通过像这样缓存导入来解决此问题:

    CREATE FUNCTION test() RETURNS text
    LANGUAGE plpythonu
    AS $$
    if 'json' in SD:
        json = SD['json']
    else:
        import json
        SD['json'] = json
    
     return json.dumps(...)
    $$;
    

    这当然不是很漂亮,并且正在讨论更好的方法来做到这一点,但它们不会在 PostgreSQL 9.4 之前发生。

    【讨论】:

    • 啊,只有在您回答之后,我才在文档中查找了一个全局字典 SD。非常感谢。
    • @Peter Eisentraut 你知道在最近的 pg 版本中是否对此问题有任何改进?
    • 这里没有任何变化。
    • 现在怎么样?另外,你会在哪里找到这种变化?
    • 这仍然是在 PostgreSQL 11 及更高版本中处理慢速导入的推荐方法吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-09
    • 2020-04-12
    • 1970-01-01
    相关资源
    最近更新 更多