免责声明:我是python和IronPython的新手,很抱歉,如果这很明显的话。
我们有一个使用IronPython执行脚本的C#应用程序。有一些常见的模块/脚本,然后有很多小脚本定义参数,进行设置,然后调用核心模块中的函数。在最近的一些新增功能使得通用模块更大的性能受到了进口的打击。我试图通过确保我们只创建一个引擎并为每个要运行的脚本创建范围来解决这个问题。我已经看到了这些在引擎上编译的信息,但显然不是这样,因为它继续花费过多的时间导入它们必须缓存在范围内。然后我使用THIS博客条目创建了一个自定义共享字典,我可以在app load上预编译公共模块,然后重用它。一切都工作正常,直到我意识到变量在后续运行中没有变化。在创建运行脚本的范围后,我将添加一个必需的变量...
currentScope.SetVariable("agr", aggregator)
第一次运行agr在脚本中工作正常,并说实例 A 。在后续运行中,将创建一个新范围,创建一个新的聚合器(让我们称之为 B )并设置为agr,但是当底层模块调用agr时,它不是聚合器 B ,其聚合器 A ,我不再有效。我甚至试图强迫它将它添加到主脚本中......
CommonModule.agr = agr
#Do Work
CommonModule.agr = None
无济于事。 agr本身不存储在共享符号字典中,但CommonModule是,它有一个agr变量。我该怎么做才能更改这个变量,为什么以这种方式缓存它?
澄清更新:对于混淆感到抱歉,但它是C#和python中很多代码的组合,很难包含。让我看看我是否可以澄清一点。每次运行脚本时,我都需要将'agr'的值设置为一个新对象,该对象是在使用scope.SetVariable()执行python之前在C#中创建的。一些核心模块被导入并编译到缓存范围中。在脚本执行时,使用使用共享作用域创建的SharedSymbolDictionary创建新的临时作用域(以避免每次导入核心模块)执行脚本。
问题是第一次在主脚本和核心(预编译)脚本中正确设置'agr',但是在后续脚本执行'agr'在主脚本中是正确的,但是当核心脚本引用时' agr'它指向'agr'创建了第一个执行而不是为该执行创建的新'agr'对象,并且它的大多数引用现在都为null。
答案 0 :(得分:0)
没有代码的所有评论都有点令人困惑。 但是只取最后一段,如果你想从C#修改模块级变量,你可以:
# scope is SharedSymbolDictionary
var module = scope.GetVariable("CommonModule") as PythonModule;
module.Get__dict__()["agr"] = "new value";
第二个观察结果,作为sharedScope提供给SharedSymbolDictionary的变量可以在单个运行中更改,但在后续运行中消失。如果您想在脚本运行期间进行持久更改,则需要将TrySetExtraValue更改为以下内容:
protected override bool TrySetExtraValue(string key, object value) {
lock (_sharedScope) {
if (_sharedScope.ContainsVariable(key)) {
_sharedScope.SetVariable(key, value);
return true;
}
return false;
}
}
注意:我使用Ironpython 2.7和.Net 4.0。 TrySetExtraValue的签名与博客中的签名略有不同。
答案 1 :(得分:0)
所以我没有一个可靠的解释,但我找到了一个简单的解决方案。最初'agr'是在任何地方使用的变量名... scope.SetVariable(),在顶级脚本中,以及在预编译的核心脚本中。
对于修复,我更改了C#以使用变量名'aggregator'来设置SetVariable()。然后我创建了一个由所有顶级主要脚本导入的模块,即sharedModule,然后使用...
sharedModule.agr = aggregator
然后我将所有核心脚本更改为使用sharedModule.agr而不仅仅是'agr',这似乎按照我想要的方式工作。