我有一个C#应用程序,它将python脚本文件(* .py)存储为字符串。我使用以下方式加载它们:
foreach
但是现在我有多个脚本文件,它们之间有依赖关系(导入)。为了处理依赖项,我可以将所有字符串保存回文件夹中的文件并加载我想要执行的脚本:
scriptEngine.CreateScriptSourceFromString(code);
但这会使所有脚本文件都可见。有没有办法以内存方式实现这一点,以便脚本文件不会首先保存到磁盘,而是直接从字符串加载?
TL; DR:示例如下:
myutils.py:
scriptEngine.CreateScriptSourceFromFile(filePath);
script1.py:
def SomeMethod(p):
print ('SomeMethod(p=%s)' % p)
script2.py:
import myutils;
if __name__ == '__main__':
myutils.SomeMethod('script1')
我的应用程序将脚本存储为字符串。
之类的东西import myutils;
if __name__ == '__main__':
myutils.SomeMethod('script2')
我想调用script1.py而不必先将脚本保存到文件夹中。注意:代码只是我所拥有的简化示例。
答案 0 :(得分:3)
一般来说,IronPython和Python中有多种自定义导入处理方法。大多数概念都在PEP 0302(新导入挂钩)中定义。
可以解决要求的两个python机制是 meta_path 和 path_hooks 。两者都可以用Python或(在IronPython的情况下)C#/ .NET实现。鉴于问题涉及从C#托管IronPython实现导入基础设施可以以任何方式工作。
使用meta_path
IronPython附带ResourceMetaPathImporter,允许您将包含脚本的ZIP存档作为嵌入式资源。假设当前正在执行的程序集中包含此类归档文件scripts.zip
,则所需的设置可能如下所示:
var engine = Python.CreateEngine();
var sysScope = engine.GetSysModule();
List metaPath = sysScope.GetVariable("meta_path");
var importer = new ResourceMetaPathImporter(Assembly.GetExecutingAssembly(), "scripts.zip");
metaPath.Add(importer);
sysScope.SetVariable("meta_path", metaPath);
如果已知程序集和脚本且ZIP打包不会干扰开发过程,则此方法很有效。
使用path_hooks
路径挂钩包含一系列导入器,可以查询sys.path
中的所有项目,以确定它们是否可以处理给定路径。类似于zipimport.cs的导入程序,但负责DLL / EXE中的嵌入资源而不是ZIP存档。
这可以提供一种更通用的方法,只需在路径中添加DLL即可处理其他文件。
使用PlatformAdaptationLayer
第三种方法是提供PlatformAdaptationLayer,它是Microsoft.Scripting
/ IronPython的一部分。 This answer显示了平台适配层的完整工作示例,该层解析了预定义程序集和程序包命名空间的嵌入资源。
一般说明:相关issue/discussion on github。
答案 1 :(得分:0)
您可以将不同的脚本创建为一个函数,并根据给定的参数调用这些函数
ScriptScope scope = scriptEngine.CreateScope();
scope.SetVariable("language", "en");
scriptEngine.Execute(scope);
和python(我知道的愚蠢的例子):
def doEnStuff():
print "english"
def doEsStuff():
print "espagna"
if language == "en"
doEnStuff()