2011-03-13 43 views
4

我正在通过IronPython为我的C#地图制作应用程序提供可扩展性机制。一切工作正常,但我有我在实施麻烦的特定需求:我希望用户能够指定两件事情:C#中的IronPython集成:特定的问题/问题

  1. 的Python脚本的文件名来加载
  2. 一包含Python脚本的单行线,其将典型是从了Python文件中的函数的调用(例如getTextLabel(element)

这两个设置必须是独立的,但我不知道是否有可能做到这一点使用PythonScript和相关的类。

我是Python的新手,也许有另一种方法来实现这一目标?出于性能原因,我想避免加载和编译Python脚本文件几次(因为可能有几个上述提到的“函数调用”设置,如果可能的话,我想重新使用CompiledCode实例)。

更新:@digEmAll给了我的问题的正确答案,所以我接受它作为一个有效的答案。但如果你关心表现,你也应该看看我自己的答案。

回答

5

你可以做这样的事情:

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

只要你保持在模块被加载的scope,你可以调用模块的功能,而无需重新加载它。

+0

谢谢,我会做一些测试,如果这工作正常,我会接受你的答案。顺便说一句,有克隆范围的方法吗?例如,为了避免一个函数调用影响后续函数调用的执行? – 2011-03-14 04:24:14

+0

嗯,我不认为这是可能的...如果是这样,它不会比创建一个新的范围和重新加载所需的模块快得多... – digEmAll 2011-03-14 07:57:45

+0

您的代码运行,感谢您的帮助。也检查出我自己的答案。 – 2011-03-14 18:05:16

4

我已经做了一些@ digEmAll的代码的测试。首先,我必须说它正确运行,并按照我在问题中提出的问题进行。但我担心你必须致电

string expr = "functionOfMyModule()"; 
var result = engine.Execute(expr, scope); 

每次你想评估一个用户定义的表达式。我的担心是代码没有预先编译,每次执行都必须重新编译,这可能会严重影响我的应用程序的性能(这些表达式可能被称为数十万次,如果不是数百万次,那么每毫秒计数)。

我尝试了不同的解决方案:只需粘贴的用户定义的表达在Python模块的结束(我不是说这适用于所有情况!):

def simpleFunc(x): 
    return x + 2; 

# this is where the pasting occurs: 
simpleFunc(x) 

我当时那么,什么是编译这段代码:

ScriptSource source = engine.CreateScriptSourceFromString(myCode); 
CompiledCode compiledCode = source.Compile(); 

...创建范围并运行它:

ScriptScope scope = engine.CreateScope(); 
scope.SetVariable ("x", 10); 
int result = compiledCode.Execute<int>(scope); 

现在我执行对同一段代码和相同的表达10000次这两个解决方案(digEmAll和我本人)和这里的结果:

  • engine.Execute(表达式,范围):0.29毫秒/运行
  • compiledCode .Execute(范围):0。01 ms/run

所以我想我会尝试使用我自己的解决方案,除非代码粘贴证明是一个问题。

+0

是的,这也很好。当然,编译代码(并保存一个调用Execute)速度更快,我没有想到;) – digEmAll 2011-03-14 18:15:52

+0

伙计们,如果在'C#'一侧你不知道参数/变量名称,并想用真正的价值观,比如'A if B> C else D'这样给出的表达式,你会如何用实数代替这些参数A,B,C,D?我只有这样的表达字符串。提前致谢 – sll 2012-03-16 20:32:09