Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-apps-script/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从模块中访问脚本作用域变量_C#_Python_Ironpython - Fatal编程技术网

C# 从模块中访问脚本作用域变量

C# 从模块中访问脚本作用域变量,c#,python,ironpython,C#,Python,Ironpython,我们在开源项目中使用IronPython。我在访问添加到脚本范围的变量时遇到问题,如 private ScriptScope CreateScope(IDictionary<string, object> globals) { globals.Add("starting", true); globals.Add("stopping", false); var scope = Engine.CreateScope(globals); scope.Imp

我们在开源项目中使用IronPython。我在访问添加到脚本范围的变量时遇到问题,如

private ScriptScope CreateScope(IDictionary<string, object> globals)
{
    globals.Add("starting", true);
    globals.Add("stopping", false);

    var scope = Engine.CreateScope(globals);
    scope.ImportModule("math");
    return scope;
}
从使用此代码执行的主脚本

void RunLoop(string script, ScriptScope scope)
{
    ExecuteSafe(() =>
    {
        var compiled = Engine.CreateScriptSourceFromString(script).Compile();

        while (!stopRequested)
        {
            usedPlugins.ForEach(p => p.DoBeforeNextExecute());
            CatchThreadAbortedException(() => compiled.Execute(scope));
            scope.SetVariable("starting", false);
            threadTimingFactory.Get().Wait();
        }
        scope.SetVariable("stopping", true);
        CatchThreadAbortedException(() => compiled.Execute(scope));
    });
}

编辑:回应@BendEg的回答

我试过这个

scope.SetVariable("__import__", new Func<CodeContext, string, PythonDictionary, PythonDictionary, PythonTuple, object>(ResolveImport));

现在,导入代理将触发,但它在第一行崩溃,因为未定义全局名称“mouse”,模块中未使用鼠标。当我将自定义全局变量添加到
内置模块

时,似乎有点困惑。据我所知,导入一些模块将创建一个新的作用域。因此,当通过来自的
创建
PythonModule
实例时。。。导入…
他们有自己的范围。在此新范围中,您的公共变量不可用。如果我错了,请纠正我

解决方法:

您可以创建一些保存值的静态类。你可以肯定的是,你总是拥有它们。例如:

namespace someNS
{
    public static class SomeClass
    {
        public static bool Start { get; set; }
    }
}
而不是在您的IP代码中:

from someNS import SomeClass

# Now you can access the member
yourVal = SomeClass.Start
也许这是你可以用的东西。事件不需要在范围中将其设置为变量

编辑

也许这对你有用。在代码中,我覆盖模块导入并尝试设置全局变量:

您需要做的第一件事是,为IronPython提供一些委托,用于模块导入:

# Scope should be your default scope
scope.SetVariable("__import__", new ImportDelegate(ResolveImport));
然后覆盖导入功能:

private object ResolveImport(CodeContext context, string moduleName, PythonDictionary globals, PythonDictionary locals, PythonTuple fromlist)
{
    // Do default import but set module
    var builtin = IronPython.Modules.Builtin.__import__(context, moduleName, globals, locals, fromlist, 0);
    context.ModuleContext.Module.__setattr__(context, "some_global", "Hello World");
    return builtin;
}
编辑

ImportDelegate的定义

delegate object ImportDelegate(CodeContext context, string moduleName, PythonDictionary globals, PythonDictionary locals, PythonTuple fromlist);

这可能不是正确的答案,因为仍然不允许将主IronPhyton脚本中定义的变量与导入的模块共享,但是这是向前迈出的一步

这种方法允许在引擎级别而不是脚本级别设置变量,并且它们将在每个导入的模块中可用

engine = Python.CreateEngine();
engine.Runtime.Globals.SetVariable("test_global", "This is a test global variable.");
然后,在任何IronPhyton脚本中,都可以使用导入来访问它:

import test_global
print(test_global)
与ScriptScope不同,ScriptScope使它们直接可用,这些全局变量需要导入

原创文章

免责声明

我添加了这个答案,因为除了这个问答之外,我一直在努力寻找关于这个主题的任何材料,所以我发布了这个可能的解决方法,以帮助未来的麻烦读者(像我自己)

你能提供一个更完整的例子吗(例如,针对这个范围执行了什么以及它是如何失败的)?有什么解决方法吗?因为我们真的需要从任何代码中访问全局静态变量,恐怕这不是一个可靠的解决方案。我们有一个插件结构,每个插件都在作用域上注册了一个名称,这样你就可以像mouse.deltaX或keyboard一样访问它。getKey(Key.a)使用一些静态的
DynamicObject
?@Anders我有更好的解决方案给你,请等2分钟:)只是想深入了解一下IronPython的核心,我们公司使用IronPython,因此,目前与之有很大关系:)
delegate object ImportDelegate(CodeContext context, string moduleName, PythonDictionary globals, PythonDictionary locals, PythonTuple fromlist);
engine = Python.CreateEngine();
engine.Runtime.Globals.SetVariable("test_global", "This is a test global variable.");
import test_global
print(test_global)