【发布时间】:2019-06-12 18:38:03
【问题描述】:
我有一个名为Contemplate 的模板引擎,它具有php、node/js 和python 的实现。
除了最近 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