如何在C#中提取IronPython脚本参数的名称

时间:2015-07-27 16:56:06

标签: c# python ironpython

我有一个Python脚本如下:

def VSH(GR, GRsand, GRshale): 
    '''Calculates Vsh from gamma inputs'''
    value = (((GR-GRsand)/(GRshale-GRsand)))
    if (value > 100.0):
      value = 100.0
    elif (value < 0.0):
        value = 0.0
    return value

来自C#我有一个循环,在IronPython 2.2中将提取3个参数。

foreach (string variableName in (PythonTuple)inputFunction.func_code.co_varnames)
{
    // do something here
}

现在在IronPython 2.7.5中,我得到了4个变量的名称,这是有道理的,但打破了旧代码。从我看到的手表:

co_varnames tuple, 4 items  IronPython.Runtime.PythonTuple
[0] "GR"    object {string}
[1] "GRsand"    object {string}
[2] "GRshale"   object {string}
[3] "value" object {string}

查看调试器中的对象inputFunction.func_code,我没有看到任何只返回参数的东西。我确实看到属性co_argcount = 3.如果我可以确定参数总是在变量列表中的第一个,那么我可以用它来过滤掉局部变量。有什么建议吗?

1 个答案:

答案 0 :(得分:1)

这是我的解决方案:

// using System.Reflection;
dynamic func = scope.GetVariable("VSH");
var code = func.__code__;
var argNamesProperty = code.GetType().GetProperty("ArgNames", BindingFlags.NonPublic | BindingFlags.Instance);
string[] argNames = (string[])argNamesProperty.GetValue(code, null);
// argNames = ["GR", "GRsand", "GRshale"]

您正在寻找合适的地方,但不幸的是IronPython.Runtime.FunctionCode.ArgNames财产是私有的。通过反射,我们可以忽略它,并且无论如何只需获取参数名称。

这是我完整的测试设置:

static void Main(string[] args)
{
    ScriptEngine engine = Python.CreateEngine();
    ScriptScope scope = engine.CreateScope();
    ObjectOperations ops = engine.CreateOperations();
    ScriptSource source = engine.CreateScriptSourceFromString(@"
def VSH(GR, GRsand, GRshale): 
    '''Calculates Vsh from gamma inputs'''
    value = (((GR-GRsand)/(GRshale-GRsand)))
    if (value > 100.0):
        value = 100.0
    elif (value < 0.0):
        value = 0.0
    return value");
    CompiledCode compiled = source.Compile();
    compiled.Execute(scope);

    dynamic func = scope.GetVariable("VSH");
    var code = func.__code__;
    var argNamesProperty = code.GetType().GetProperty("ArgNames", BindingFlags.NonPublic | BindingFlags.Instance);
    string[] argNames = (string[])argNamesProperty.GetValue(code, null);
    // argNames = ["GR", "GRsand", "GRshale"]
}

我确定您可以减少dynamic func = ...行之前的所有内容,因为您可能已经可以访问VSH功能。