我试图在Python中组建一个小型构建系统,为我的C ++项目生成Ninja文件。它的行为应该类似于CMake;也就是说,that.setState()
脚本定义规则和目标,并可选择通过调用bldfile.py
将其递归到一个或多个目录中。每个bld.subdir()
脚本都有一个对应的bldfile.py
对象。执行bld.File
脚本时,bldfile.py
全局应预定义为该文件的bld
实例,但仅限于该模块的范围
此外,我想以某种方式利用Python的字节码缓存,但bld.File
文件应该存储在构建输出目录中,而不是存储在.pyc
目录旁边的__pycache__
目录中。 {1}}脚本。
我知道我应该使用bldfile.py
(要求Python 3.4+很好),但我不确定如何:
非常感谢任何帮助!
答案 0 :(得分:1)
我研究了importlib
的源代码,因为我不打算重复使用Loader
,所以看起来似乎有很多不必要的复杂性。所以我决定使用types.ModuleType
创建一个模块,将bld
添加到模块的__dict__
,使用compile
编译和缓存字节码,并使用{{1}执行模块}}。在较低的水平上,无论如何基本上都是exec
。
答案 1 :(得分:1)
在执行之前将全局变量注入模块是一个有趣的想法。但是,我认为它与Zen of Python的几个点有冲突。特别是,它需要在模块中编写代码,该代码依赖于未明确定义,导入或以其他方式获得的全局值 - 除非您知道调用模块所需的特定过程。
对于特定用例,这可能是一个明显或光滑的解决方案,但它不是非常直观。通常,(Python)代码应该是显式的。因此,我会寻求一个解决方案,其中参数显式传递给执行代码。听起来像功能?右:
<强> bldfile.py 强>
def exec(bld):
print('Working with bld:', bld)
# ...
调用模块:
# set bld
# Option 1: static import
import bldfile
bldfile.exec(bld)
# Option 2: dynamic import if bldfile.py is located dynamically
import importlib.util
spec = importlib.util.spec_from_file_location("unique_name", "subdir/subsubdir/bldfile.py")
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
module.exec(bld)
这样,导入模块时不会执行任何代码(除了函数定义)。需要明确调用exec
函数,在查看exec
中的代码时,bld
来自何处。
答案 2 :(得分:0)
可以使用虚拟模块克服这种可能性的不足,该模块将加载其全局变量。
#service.py
module = importlib.import_module('userset')
module.user = user
module = importlib.import_module('config')
#config.py
from userset import *
#now you can use user from service.py