2011-03-13 37 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