I'm working on providing an extensibility mechanism for my C# mapmaking application through IronPython. Everything works fine, but I have a specific requirement which I'm having trouble implementing: I want the user to be able to specify two things:
getTextLabel(element)
)These two settings must be separate, but I don't know if it is possible to do this using PythonScript
and related classes.
I'm a newbie in Python, perhaps there is another way to achieve this? For performance reasons I want to avoid loading and compiling the Python script file several times (since there could be several above mentioned different "function call" settings and I want to reuse the CompiledCode
instance for the file if possible).
UPDATE: @digEmAll gave the correct answer to my question, so I'm accepting it as a valid answer. But if you are concerned with performance, you should also check out my own answer.
You can do something like this:
string importScript = "import sys" + Environment.NewLine +
"sys.path.append( r\"{0}\" )" + Environment.NewLine +
"from {1} import *";
// python script to load
string fullPath = @"c:\path\mymodule.py";
var engine = Python.CreateEngine();
ScriptScope scope = engine.CreateScope();
// import the module
string scriptStr = string.Format(importScript,
Path.GetDirectoryName(fullPath),
Path.GetFileNameWithoutExtension(fullPath));
var importSrc = engine.CreateScriptSourceFromString(scriptStr,Microsoft.Scripting.SourceCodeKind.File);
importSrc.Execute(scope);
// now you ca execute one-line expressions on the scope e.g.
string expr = "functionOfMyModule()";
var result = engine.Execute(expr, scope);
As long as you keep the scope
where the module is loaded, you can call functions of the module without reloading it.
I've done some testing of @digEmAll's code. First I must say it runs correctly and does what I asked in the question. But I was concerned with the fact that you have to call
string expr = "functionOfMyModule()";
var result = engine.Execute(expr, scope);
every time you want to evaluate a user-defined expression. My concern was that the code is not pre-compiled and has to be reparsed on each execution, which could have a serious effect on the performance of my application (these kinds of expressions could be called hundreds of thousands if not millions of times, so every millisecond counts).
I tried a different solution: simply pasting the user-defined expression at the end of the Python module (I'm not saying this works in all situations!):
def simpleFunc(x):
return x + 2;
# this is where the pasting occurs:
simpleFunc(x)
What I did then is to compile this code:
ScriptSource source = engine.CreateScriptSourceFromString(myCode);
CompiledCode compiledCode = source.Compile();
... create a scope and run it:
ScriptScope scope = engine.CreateScope();
scope.SetVariable ("x", 10);
int result = compiledCode.Execute<int>(scope);
Now I executed both solutions (digEmAll's and my own) on the same piece of code and the same expression 10,000 times and here are the results:
So I guess I'll try to use my own solution, unless the code pasting proves to be a problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With