从模块访问脚本范围变量

2024-09-27 09:35:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我们在开源项目中使用了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;
}

https://github.com/AndersMalmgren/FreePIE/blob/master/FreePIE.Core/ScriptEngine/Python/PythonScriptEngine.cs#L267

我可以使用主脚本中的全局变量,但加载的任何模块都将失败。怎么能修好?在

更新:鉴于此模块我的模块.py

^{pr2}$

从使用此代码执行的主脚本

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));
    });
}

https://github.com/AndersMalmgren/FreePIE/blob/master/FreePIE.Core/ScriptEngine/Python/PythonScriptEngine.cs#L163

from mymodule import * #this will load the moduel and it fails with

enter image description here

编辑:回应@本德的回答

我试过了

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

ImportDelegate未定义,因此尝试使用funct代替,ResolveImport方法从不触发,并且我得到的异常与未定义名称相同

编辑:我将作用域创建更改为

var scope = Engine.GetBuiltinModule();
globals.ForEach(g => scope.SetVariable(g.Key, g.Value));

现在import委托触发了,但是它在第一行崩溃了global name 'mouse' is not defined,在模块中没有使用鼠标。当我将自定义全局参数添加到BuiltinModule中时,似乎很困惑


Tags: 模块import脚本stringobjectvar作用域engine
1条回答
网友
1楼 · 发布于 2024-09-27 09:35:49

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

解决方法:

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

namespace someNS
{
    public static class SomeClass
    {
        public static bool Start { get; set; }
    }
}

而不是你的IP代码:

^{pr2}$

也许这是你可以用的东西。事件不需要在作用域中将其设置为变量。在

编辑

也许这对你有用。在代码i重写模块导入并尝试设置全局变量:

您需要做的第一件事是,给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);

相关问题 更多 >

    热门问题