鱼C论坛

 找回密码
 立即注册
查看: 2637|回复: 0

[学习笔记] c# 调用Python踩坑指南 ------ python.net

[复制链接]
发表于 2021-3-9 10:58:19 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
### Python.NET

Python.NET (`pythonnet`) is a package that gives Python programmers nearly seamless integration(无缝连接) with the .NET 4.0+ Common Language Runtime (CLR) on Windows and Mono runtime on Linux and OSX. Python.NET provides a powerful application scripting tool for .NET developers. Using this package you can script .NET applications or build entire applications in Python, using .NET services and components written in any language that targets the CLR (C#, VB.NET, F#, C++/CLI).

### 安装

`pip install pythonnet`



## Python net 调用 .Net代码



(Pythonnet 暂时只支持Framework生成的dell)



#### 1.1 简单的计算dll

```C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PythonTest
{
    public class calculate //一定为public!!!
    {
        public int Add(int a, int b) {
            return a + b;
        }

        public int Sub(int a, int b) {
            return a - b;
        }
    }

```

其中:

      - 域名:PythonTest
   
    - 类名称: caculsate
    - 方法名称:Add, Sub
    - 可以随便修改所生成的dll名称



#### 1.2如何在python中使用dll

```python
assemblu_Path =r"C:\Users\huqinggang\source\repos\PythonTest\bin\Debug"

import sys
sys.path.append(assemblu_Path)
```

assemblu_Path 字符串用于存储路径

sys.pasysth.append() 方法用于添加存储路径



添加程序集

```python
import clr
clr.AddReference("PythonTest")//PythonTest为dll的名称
```



导入对象

```
from PythonTest import calculate
```

PythonTest 为 namespace

calculate 为 类名称

使用导入对象

```python
ct = calculate()
print(ct.Add(1,1))

params = [1,2]
print(ct.Sub(*params))
```

Output

```
PS E:\Python> python example.py
2
-1
```





####  2.使用Class

python.net 允许你使用任何 **非私有Class,structs,interface,enums,delegates**

```python
from System.Drawing import Point
p = Point(5,5);
```

output:

```
PS E:\Python> python example.py
{X=5,Y=5}
```

默认情况下python.net会根据参数自动匹配构造器。

特殊情况下,需要使用**Overload** 去调用构造器

```python
from System import String, Char, Int32

s = String.Overloads[Char, Int32]('A', 10)
s = String.__overloads__[Char, Int32]('A', 10)//_overload_不久后将弃用为了兼容ipy
```

Output:

```
PS E:\Python> python example.py
AAAAAAAAAA
AAAAAAAAAA
```



#### 3.使用泛型

Python.net 支持泛型,一个泛型类在实例化之前,必须明确创建的具体类型

```python
from System.Collections.Generic import Dictionary
from System import *

dict1 = Dictionary[String, String]()
dict2 = Dictionary[String, Int32]()
dict3 = Dictionary[String, Type]()

dict1.Add("hello","Hello,Mark")


dict4 = Dictionary[str, str]()
dict5 = Dictionary[str, int]()
dict6 = Dictionary[str,Decimal]()

dict4.Add("hello","Hello,Mark subscript")


print(dict1["hello"])
print(dict4["hello"])
```

Output:

```
PS E:\Python> python example.py
Hello,Mark
Hello,Mark subscript
```



#### 4.读取和写入字段,属性

```python
import clr
from System import Environment

//读取
name = Environment.MachineName
exitcode = Environment.ExitCode
print(name)
print(exitcode)

//写入
Environment.ExitCode = 1
exitcode = Environment.ExitCode
print(exitcode)
```



Output:

```
PS E:\Python> python example.py
DESKTOP-GUOCCNK
0
1
```



#### 5.使用方法

```python
from System import Environment

drives = Environment.GetLogicalDrives()
```



查看对象中可以使用方法

` help(Environment)`

Output:

```c#
|  ExpandEnvironmentVariables
|      System.String ExpandEnvironmentVariables(System.String)
|
|  FailFast
|      Void FailFast(System.String)
|      Void FailFast(System.String, System.Exception)
|
|  GetCommandLineArgs
|      System.String[] GetCommandLineArgs()
|
|  GetEnvironmentVariable
|      System.String GetEnvironmentVariable(System.String)
|      System.String GetEnvironmentVariable(System.String, System.EnvironmentVariableTarget)
|
|  GetEnvironmentVariables
|      System.Collections.IDictionary GetEnvironmentVariables()
|      System.Collections.IDictionary GetEnvironmentVariables(System.EnvironmentVariableTarget)
|
|  GetFolderPath
|      System.String GetFolderPath(SpecialFolder)
|      System.String GetFolderPath(SpecialFolder, SpecialFolderOption)
|
|  GetLogicalDrives
|      System.String[] GetLogicalDrives()
|
```



#### 6.Overload 和 泛型

例子

```python
from System import Console

//console.writeline 有多种传入类型
Console.WriteLine.Overloads[bool](true)

```

```
PS E:\Python> python example.py
true
```



#### 7.异常处理

```python
from System import NullReferenceException

try:
    raise NullReferenceException("aiieee!")
except NullReferenceException as e:
    print(e.Message)
    print(e.Source)
```



#### 8.Array使用

  ```python
from System import Array

myarray = Array[int](10)
  ```

上面为官方提供的代码无法使用

```python
from System import Array

myarray = Array.CreateInstance(int,10)
myarray[0]= 10
myarray[1] =20
myarray[20]=30//报错超出范围

print(myarray[0])
print(myarray[1])
print(len(myarray))

```



#### 9.集合

可以使用Python的for in 语法 对实现 IEnmerable 接口的对象迭代

```python
domin = System.AppDomain.CurrentDomain

for item in domin.GetAssemblies():
    name = item.GetName()
    print(name)
```



#### 10.类型转换

```python
import clr
from System import Array
from System.Drawing import Point

items = Array.CreateInstance(Point,3)

for i in range(3):
    items[i] = Point(0, 0)

items[0].X = 1 //报错

```

compiled-to-IL languages 的编译器知道Point 是一种值类型所以可以直接对对象改变它的值



对于Python,所有对象都是引用,需要进行拆装箱对对象的值进行改变



正确做法

```
items = System.Array.CreateInstance(Point, 3)
for i in range(3):
    items[i] = Point(0, 0)

item = items[0]//拆箱
item.X = 1
items[0] = item//装箱
```



## C# 调用 Python

- 添加引用 Python.Runtime.dll
- 调用PythonEngine.Initialize()对Python初始化
- 调用PythonEngine.ImportModule(name)引入对象



#### 可能出现的问提:

​      找不到DLL"无法加载pythonxx":

* 添加环境变量
* 添加Cpython

在代码中添加Cpython

```c#
    string envPythonHome = @"C:\Python370";
            string envPythonLib = envPythonHome + @"\Lib\site-packages";
            PythonEngine.PythonHome = envPythonHome;
            PythonEngine.PythonPath = Environment.GetEnvironmentVariable("PYTHONPATH");
            Environment.SetEnvironmentVariable("PYTHONHOME", envPythonHome, EnvironmentVariableTarget.Process);
            Environment.SetEnvironmentVariable("PATH", envPythonHome + ";" + Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Machine),
                EnvironmentVariableTarget.Process);

            Environment.SetEnvironmentVariable("PYTHONPATH", envPythonLib, EnvironmentVariableTarget.Process);

            PythonEngine.Initialize();
```



c# 调用 python 库

```c#
  PythonEngine.Initialize();


   using (Py.GIL()) {
                dynamic np = Py.Import("numpy");
                Console.WriteLine(np.cos(np.pi * 2));

                dynamic sin = np.sin;
                Console.WriteLine(sin(5));

                double c = np.cos(5) + sin(5);
                Console.WriteLine(c);

                dynamic a = np.array(new List<float> { 1, 2, 3 });
                Console.WriteLine(a.dtype);

        dynamic b = np.array(new List<float> { 6, 5, 4 }, dtype: np.int32);
                Console.WriteLine(b.dtype);

                Console.WriteLine(a * b);
                Console.ReadKey();
```

安装numpy

` python -m pip install numpy`

Output:

```
1.0
-0.9589242746631385
-0.675262089199912
float64
int32
[ 6. 10. 12.]
```



### 细节

* 调用Python 在`using (Py.GIL()){......在这里调用python..........}`

* 导入pythom 模块

  ` dynamic mod  = Py.Import(numpy)`

  调用python 方法

  ` Console.WriteLine(mod.cos(np.pi * 2));`

* 所有python的对象 只能用 **Dynamic** 类型接收!!!

* 所有数学操作涉及到python,python的对象一定要前置

  例如 : python.PI * 2 **(可执行)**

  &#8203;              2 * python.PI **(报错)**





想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-20 19:34

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表