【问题标题】:Python: Dynamicaly imported module fails when first created, then succeedsPython:第一次创建时动态导入模块失败,成功
【发布时间】:2019-06-12 18:38:03
【问题描述】:

我有一个名为Contemplate 的模板引擎,它具有phpnode/jspython 的实现。

除了最近 python 实现给我带来了一些问题外,一切都很好。具体来说,首先解析模板并创建模板python代码时会出现问题,然后将其作为模块动态导入。当模板已经创建时,一切正常,但是当需要解析模板并将其保存到磁盘然后导入时,它会引发错误,例如

ModuleNotFoundError: No module named 'blah blah'

(注意这个错误似乎是随机的,它并不总是确定它会被引发,很多时候即使模板是在导入之前创建的,其他时候它会失败,然后如果使用已经创建的模板再次运行它成功)

有什么办法可以绕过这个问题,也许在保存解析的模板和导入为模块或其他东西之间添加延迟?

导入模块的代码(解析后的模板现在是一个python类)如下:

def import_tpl( filename, classname, cacheDir, doReload=False ):
    # http://www.php2python.com/wiki/function.import_tpl/
    # http://docs.python.org/dev/3.0/whatsnew/3.0.html
    # http://stackoverflow.com/questions/4821104/python-dynamic-instantiation-from-string-name-of-a-class-in-dynamically-imported

    #_locals_ = {'Contemplate': Contemplate}
    #_globals_ = {'Contemplate': Contemplate}
    #if 'execfile' in globals():
    #    # Python 2.x
    #    execfile(filename, _globals_, _locals_)
    #    return _locals_[classname]
    #else:
    #    # Python 3.x
    #    exec(read_file(filename), _globals_, _locals_)
    #    return _locals_[classname]

    # http://docs.python.org/2/library/imp.html
    # http://docs.python.org/2/library/functions.html#__import__
    # http://docs.python.org/3/library/functions.html#__import__
    # http://stackoverflow.com/questions/301134/dynamic-module-import-in-python
    # http://stackoverflow.com/questions/11108628/python-dynamic-from-import
    # also: http://code.activestate.com/recipes/473888-lazy-module-imports/
    # using import instead of execfile, usually takes advantage of Python cached compiled code

    global _G
    getTplClass = None
    # add the dynamic import path to sys
    basename = os.path.basename(filename)
    directory = os.path.dirname(filename)
    os.sys.path.append(cacheDir)
    os.sys.path.append(directory)
    currentcwd = os.getcwd()
    os.chdir(directory)   # change working directory so we know import will work

    if os.path.exists(filename):

        modname = basename[:-3]  # remove .py extension
        mod = __import__(modname)
        if doReload: reload(mod) # Might be out of date
        # a trick in-order to pass the Contemplate super-class in a cross-module way
        getTplClass = getattr( mod, '__getTplClass__' )

    # restore current dir
    os.chdir(currentcwd)
    # remove the dynamic import path from sys
    del os.sys.path[-1]
    del os.sys.path[-1]

    # return the tplClass if found
    if getTplClass:  return getTplClass(Contemplate)
    return None

注意引擎会在cacheDir 中创建一个__init__.py 文件(如果该文件尚不存在)。

如果需要,我可以将import_tpl 函数更改为其他我不介意的。

windows 上测试的 Python 是 python 3.6,但我认为这不是特定于平台的问题。

要测试问题,您可以下载github 存储库(上面链接)并在清除/tests/_tplcache/ 文件夹中的所有缓存模板后运行/tests/test.py 测试

更新:

我正在考虑在import_tpl 中添加一个带有一些计数器的while 循环,该循环会捕获引发的错误(如果有)并重试指定次数,直到它成功导入模块。但我也想知道这是否是一个好的解决方案,或者我在这里还缺少其他东西..

更新(2019 年 2 月 20 日):

添加了一个循环以重试指定的次数,如果最初无法导入模板模块(请参阅在线存储库代码),则添加 1 秒的小延迟,但有时在导入之前首次创建模板时仍会引发相同的错误。有什么解决办法吗?

【问题讨论】:

    标签: python-3.x dynamic python-import


    【解决方案1】:

    好吧,如果您使用“while”循环来处理异常将是一种方法。

    while True:
        try:
            #The module importing
            break
        except ModuleNotFoundError:
            print("NOPE! Module not found")
    

    如果它适用于其他一些,而不是其他“模块”文件,则可能的嫌疑人是模板文件本身。

    【讨论】:

    • 知道为什么会发生这种情况,为什么会随机发生,有时会发生有时不会,使用相同的模板。特别是如果一个模板扩展了另一个模板,这是我见过最多的。可能是磁盘问题,还是 python 问题?
    • 我已经添加了一个 while 循环,它会重试导入模块指定的次数,如果不能,则返回(还更新了 github 存储库)。但我想知道这是否是我能找到的最佳解决方案..
    • 嗯,现在 git 正在克隆 repo,请给我一些时间检查一下,看看我想出了什么。希望你能在我做之前得到答案。
    • 即使在我添加了代码以重试特定次数(例如 3 次)并且我在重试之前添加了 1 秒的小延迟后,我仍然收到相同的错误。有什么新想法吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-31
    • 2013-12-03
    • 2020-05-21
    • 2017-12-26
    • 1970-01-01
    • 2011-12-25
    • 1970-01-01
    相关资源
    最近更新 更多