如何在 C# 中提取 IronPython 脚本参数的名称
How do I extract the names of IronPython script arguments in C#
我有一个 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
我在 IronPython 2.2 中使用 C# 中的循环提取 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,我没有看到任何 return 参数。我确实看到了 属性 co_argcount = 3。如果我能确定参数总是在变量列表中排在第一位,那么我就可以用它来过滤掉局部变量。有什么建议吗?
这是我的解决方案:
// 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"]
}
我相信您可以 trim 记下 dynamic func = ...
行之前的所有内容,因为您可能已经可以访问 VSH
函数了。
我有一个 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
我在 IronPython 2.2 中使用 C# 中的循环提取 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,我没有看到任何 return 参数。我确实看到了 属性 co_argcount = 3。如果我能确定参数总是在变量列表中排在第一位,那么我就可以用它来过滤掉局部变量。有什么建议吗?
这是我的解决方案:
// 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"]
}
我相信您可以 trim 记下 dynamic func = ...
行之前的所有内容,因为您可能已经可以访问 VSH
函数了。