C# 코드에서 python.net을 사용하여 명명된 매개 변수로 파이썬 함수를 호출
나는 C# 코드에서 파이썬 함수를 호출하고 싶다. 그러기 위해, 나는 용으로 파이썬을 사용했다.다음 코드 행에 표시된 것처럼 함수를 호출하는 NET
using System;
using Python.Runtime;
public class Test{
public static void Main(){
using(Py.GIL()){
dynamic lb = Py.Import("lb");
dynamic result = lb.analyze("SomeValue");
Console.WriteLine(result);
}
}
}
파이썬 함수는 다음과 같다:
def analyze(source, printout = False, raw = True):
# removed for bravity
그래서 문제는 C# 코드에서 분석 함수를 호출할 때 "raw"를 어떻게 설정할 수 있느냐는 것이다. 나는 다음과 같이 시도해 보았지만 소용이 없었다.
1. dynamic result = lb.analyze("SomeSource", raw : false); // No result
2. dynamic result = lb.analyze("SomeSource", @"raw = False"); // No result
나는 이것을 함으로써 하기 쉽다는 것을 안다:
dynamic result = lb.analyze("SomeSource", False, False);
하지만 이름이 지정된 매개 변수가 6~7개 이상이면 수동으로 모두 삽입하고 원하는 매개 변수를 변경하는 것은 좋지 않습니다. 예를 들어, 내가 사용하고 있는 파이썬 라이브러리에는 기본값이 없는 두 개의 추가 매개변수를 포함하여 기본값을 가진 12개의 명명된 매개변수가 있다.
나는 또한 노력했다:
3. dynamic result = lb.analyze("SomeSource", raw = false); // C# compilation error
키워드 인수를 적용하려면 다음을 사용합니다:
lb.analyze("SomeSource", Py.kw("raw", false));
봐.
또 다른 접근법은 파이썬넷에 추가된 C# 키워드 인수 구문을 사용하는 것이다:
lb.analyze("SomeSource", raw: false);
나는 파이썬 스크립트를 호출하기 위해 하나의 함수를 사용하고 있기 때문에 매개 변수 값을 유지하기 위해 목록을 사용했다. 파이썬 스크립트에 여러 기능이 있는 여러 클래스가 포함되어 있기 때문에 클래스 이름과 함수 이름도 전달하고 있습니다. 나는 어떤 수업에서도 'self' 매개 변수를 사용하지 않기 때문에, 그것들은 정적 함수이다. 나는 당신과 .net에서 파이썬을 사용하는 다른 사람들을 돕기 위해 내 코드의 일부를 제공한다. 나는 개인적으로 USB와 통신하기 위해 그것을 사용한다.
여기 제 방문자 중 한 명의 예가 있습니다. 함수 이름을 무시하고 실행 스크립트를 호출하고 매개 변수 집합을 전달하는 방법을 살펴봅니다. 매개 변수가 string/int/boole/objects 등이 혼합된 경우, 이 목록은 유형 객체입니다.
public string SendCommand(string comport, string command)
{
try
{
List<object> parameterSet = new() { comport, command };
string result = _pythonService.ExecuteScript<string>("usb", "usb", "sendCommand", parameterSet);
return result;
}
catch (Exception)
{
throw;
}
}
클래스 함수를 실행하는 함수는 다음과 같습니다
public dynamic? ExecuteScript<T>(string scriptFile, string className, string functionName, List<object> paramset)
{
T? result = default;
try
{
// Location of all the python scripts in the project. lets get the python file we are specifying in the function param
string file = $"{Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)}\\PythonScripts\\{scriptFile}.py";
// This is initalized in the program.cs, but just want to make sure it's initialized in case something happens
if (!PythonEngine.IsInitialized)
{
PythonEngine.Initialize();
Py.GIL();
}
using (var scope = Py.CreateScope())
{
PyObject? pythonReturn; // Our returned PythonObject from the python function call
string code = File.ReadAllText(file); // Get the python file as raw text
var scriptCompiled = PythonEngine.Compile(code, file); // Compile the code/file
scope.Execute(scriptCompiled); // Execute the compiled python so we can start calling it.
PyObject pythonClass = scope.Get(className); // Lets get an instance of the class in python
// Add parameters to the function?
if (paramset != null && paramset.Count > 0)
{
PyObject[] pyParams = new PyObject[paramset.Count]; // This is an array of python parameters passed into a function
// Loop through our incoming c# list of parameters and create PythonObject array .
for (int i = 0; i < paramset.Count; i++)
{
pyParams[i] = paramset[i].ToPython();
}
pythonReturn = pythonClass.InvokeMethod(functionName, pyParams); // Call the function on the class with parameters
}
else // We aren't using parameters here
pythonReturn = pythonClass.InvokeMethod(functionName); // Call the function on the class
// Lets convert our returned pythonObject to that of the object type (C#)
object? netObject = pythonReturn.AsManagedObject(typeof(object));
// A special case of when we want a list back. We will convert the object to the specific type in the caller function
if (typeof(T) == typeof(IList<object>))
{
object[] something = pythonReturn.As<object[]>();
return something;
}
// Convert the c# object to that of what we expect to be returned,. string/int/bool/class
if (netObject != null)
result = (T)netObject; // convert the returned string to managed string object
}
return result;
}
catch (Exception)
{
// Handle your exceptions here
throw;
}
}
전체 기능을 신경 쓰지 않고 매개 변수를 추가하는 간단한 스니펫만 원하는 경우:
// Add parameters to the function?
if (paramset != null && paramset.Count > 0)
{
PyObject[] pyParams = new PyObject[paramset.Count]; // This is an array of python parameters passed into a function
// Loop through our incoming c# list of parameters and create PythonObject array .
for (int i = 0; i < paramset.Count; i++)
{
pyParams[i] = paramset[i].ToPython();
}
pythonReturn = pythonClass.InvokeMethod(functionName, pyParams); // Call the function on the class with parameters
}
else // We aren't using parameters here
pythonReturn = pythonClass.InvokeMethod(functionName); // Call the function on the class
'개발하자' 카테고리의 다른 글
웹 어셈블리 바이너리가 JavaScript/TypeScript 번들보다 작습니까? (0) | 2023.02.09 |
---|---|
빌드하는 동안 플러터 공급자 setState() 또는 MarkNeedsBuild() 호출됨 (0) | 2023.02.09 |
데이터 가져오기의 python 스크립트 변수에 대한 Power BI Pass 매개 변수 값 (0) | 2023.02.08 |
파이썬에서 글로벌이 아닌 외부(포착) 범위에 있는 변수를 수정할 수 있습니까? (0) | 2023.02.07 |
Svelte: 구성 요소에서 본문에 스크롤 클래스 이름을 추가하지 않음 (0) | 2023.02.06 |