2015-07-06 9 views
3

Мы используем 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

можно использовать глобал от основного сценария, но любой модуль, который загружен не будет выполнено. Как это можно исправить?

обновление: Учитывая этот модуль mymodule.py

if starting: #starting is defined on the 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)); 
    }); 
} 

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

редактировать: В ответ на @ ответ BendEg в

Я попытался это

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

ImportDelegate не определено так пробовали использовать Func вместо этого, метод ResolveImport никогда не срабатывает и я получаю такое же исключением того, что имя не определено

редактирования: Я изменил создание возможности для

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

Теперь делегат импорта запускает, но он сбой в первой строке с global name 'mouse' is not defined, мышь не используется из модуля. Кажется, что это смущает, когда я добавляю свои пользовательские глобальные переменные в BuiltinModule

+0

Не могли бы вы предоставить более полный пример (например, что выполняется против этой области и как она терпит неудачу)? –

+0

См. Править – Anders

ответ

1

Насколько я знаю, импортирование некоторого модуля создаст новую область. Поэтому при создании экземпляра PythonModule через from ... import ... у них есть своя область. В этой новой области ваши общедоступные переменные недоступны. Пожалуйста, поправьте меня, если я ошибаюсь.

Обход:

Вы можете создать некоторый статический класс, который holdes значения. Чем вы можете быть уверены, у вас всегда есть их. Например:

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

И чем в вашем IP-Code:

from someNS import SomeClass 

# Now you can access the member 
yourVal = SomeClass.Start 

может быть, это какой-то, что вы можете использовать. Вам не нужно указывать его как переменную в области.

EDIT

Может быть, это работает для вас.В коде я переопределить модуль импортирование и попытаться установить глобальные ВАР:

Первое, что вам нужно это, дать 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; 
} 

EDIT

Определение ImportDelegate

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

Есть ли обходные пути для этого? Потому что нам действительно нужно, чтобы наши глобальные статические переменные доступны из любого кода. – Anders

+0

Взгляните на мое редактирование. – BendEg

+0

Я не боюсь твердого решения. у нас есть структура плагина, каждый плагин зарегистрирован в области с именем, чтобы вы могли получить к нему доступ, как mouse.deltaX или keyboard.getKey (Key.A) – Anders

Смежные вопросы