为什么我不能在IronPython中更改缓存模块中的变量?

为什么我不能在IronPython中更改缓存模块中的变量?,python,ironpython,Python,Ironpython,免责声明:我是python和IronPython新手,如果这是显而易见的,我非常抱歉 我们有一个C应用程序,它使用IronPython来执行脚本。有一些常见的模块/脚本,还有很多小脚本,它们定义参数、执行设置,然后调用核心模块中的函数。在最近的一些添加使通用模块更大之后,性能对导入造成了冲击。我试图通过确保只创建一个引擎并为每个脚本创建作用域来解决这个问题。我已经看到了在引擎上编译这些文件的信息,但显然不是这样,因为导入这些文件需要花费大量的时间,所以必须将其缓存在作用域中。然后,我使用blog

免责声明:我是python和IronPython新手,如果这是显而易见的,我非常抱歉


我们有一个C应用程序,它使用IronPython来执行脚本。有一些常见的模块/脚本,还有很多小脚本,它们定义参数、执行设置,然后调用核心模块中的函数。在最近的一些添加使通用模块更大之后,性能对导入造成了冲击。我试图通过确保只创建一个引擎并为每个脚本创建作用域来解决这个问题。我已经看到了在引擎上编译这些文件的信息,但显然不是这样,因为导入这些文件需要花费大量的时间,所以必须将其缓存在作用域中。然后,我使用blog条目创建了一个自定义的共享字典,在这个字典中,我可以在appload中预编译公共模块,然后重用它。一切都很顺利,直到我意识到变量在随后的运行中并没有改变。在创建了一个运行脚本的作用域之后,我会添加一个必需的变量

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”的值设置为一个新对象,该对象是在python执行之前使用scope.SetVariable在C中创建的。一些核心模块被导入并编译到缓存的作用域中。在脚本执行时,使用与共享作用域一起创建的SharedSymbolDictionary创建一个新的临时作用域,以避免每次执行脚本时都导入核心模块


问题是第一次在主脚本和核心预编译脚本中正确设置了“agr”,但是在随后的脚本执行中,“agr”在主脚本中是正确的,但是,当核心脚本引用“agr”时,它指向第一次执行时创建的“agr”,而不是为该执行创建的新“agr”对象,并且它的大多数引用现在为空

所有没有代码的注释都有点混乱。 但就最后一段而言,如果您想修改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;
        }
    }

注意:我使用IronPython2.7和.NET4.0。TrySetExtraValue的签名与博客中的签名有点不同。

因此我没有确切的解释,但我找到了一个简单的解决方案。最初“agr”是到处使用的变量名。。。scope.SetVariable,在顶级脚本和预编译的核心脚本中

为了解决这个问题,我将C改为对SetVariable使用变量名“aggregator”。然后我创建了一个由所有顶级主脚本导入的模块,即sharedModule,然后使用

sharedModule.agr = aggregator

然后,我将所有核心脚本更改为使用sharedModule.agr,而不仅仅是“agr”,这似乎是我想要的方式。

变量在后续运行中没有更改-您所说的运行是什么意思?脚本的执行。第一次执行脚本时,agr设置正确。如果我再次执行该脚本或另一个脚本,那么agr在公共模块中使用时,仍然设置为原始值,而不是由SetVariable分配的新值。我的意思是,如果在后续运行之间重新加载应用程序,您不能期望对内存中版本的内容所做的更改在后续运行之间保持不变。否,应用程序未关闭并重新启动。我说的是从C应用程序执行脚本。它接受一个现有引擎并创建一个新的作用域和一个新的agr(在作用域上设置),然后执行一个脚本,但是模块似乎总是引用原始agr,即使它已在新的作用域中设置。听起来底层模块不使用相同的作用域。。。