IronPython 综合教程
IronPython 是一个在 .NET Framework 和 Mono 上实现的 Python 编程语言,它完全兼容 Python 2.7 的语法,并且能够无缝地与 .NET 的类型库和生态系统进行交互,这使得 IronPython 成为脚本化 .NET 应用程序、快速原型开发以及利用现有 .NET 库的绝佳选择。

目录
-
第一部分:入门基础
- 1 什么是 IronPython?
- 2 为什么选择 IronPython?
- 3 环境搭建
- 4 第一个 IronPython 程序 ("Hello, World!")
- 5 IronPython 交互式环境 (REPL)
-
第二部分:核心概念与 Python 语法
- 1 变量与数据类型
- 2 控制流
- 3 函数
- 4 面向对象编程
-
第三部分:IronPython 的精髓——与 .NET 交互
- 1 导入 .NET 程序集
- 2 使用 .NET 类型和方法
- 3 处理 .NET 集合
- 4 继承和实现 .NET 接口
- 5 处理事件
-
第四部分:从 C# 调用 IronPython
(图片来源网络,侵删)- 1 设置 C# 项目
- 2 执行 Python 脚本文件
- 3 执行 Python 字符串代码
- 4 向 Python 传递参数和对象
- 5 从 Python 获取返回值
-
第五部分:实战案例
- 1 案例1:用 IronPython 脚本化 WinForms 界面
- 2 案例2:在 C# 应用中嵌入 IronPython 作为脚本引擎
-
第六部分:资源与进阶
- 1 官方文档与社区
- 2 性能考量
- 3 调试技巧
第一部分:入门基础
1 什么是 IronPython?
IronPython 是一个开源的 Python 实现,它不是将 Python 代码解释为字节码,而是直接将其编译成 .NET 的通用中间语言,这意味着 IronPython 程序就是 .NET 程序,可以运行在 .NET 运行时上(如 .NET Framework 或 .NET Core/Mono)。
2 为什么选择 IronPython?
- Python 的强大与简洁:利用 Python 丰富的库、简洁的语法和快速开发能力。
- 无缝的 .NET 集成:可以直接使用任何 .NET 程序集中的类、库和功能,如
System.Windows.Forms、Entity Framework、ASP.NET等。 - 脚本化 .NET 应用:为你的 C# 或 VB.NET 应用程序提供一个可扩展的脚本引擎,允许用户或开发者通过脚本来定制功能。
- 跨平台:基于 .NET Core,IronPython 可以在 Windows、Linux 和 macOS 上运行。
3 环境搭建
最简单的方式是使用 .NET SDK。
- 安装 .NET SDK:从 Microsoft 官网 下载并安装最新的 .NET SDK (如 .NET 6.0 或更高版本)。
- 安装 IronPython:使用 .NET 的全局工具安装器来安装 IronPython。
打开终端或命令提示符,运行以下命令:
dotnet tool install --global IronPython
安装完成后,
ipy命令就会添加到你的系统路径中。
4 第一个 IronPython 程序 ("Hello, World!")
创建一个名为 hello.py 的文件,并输入以下内容:
# hello.py
print("Hello, World from IronPython!")
在终端中,使用 ipy 命令运行它:
ipy hello.py
输出:
Hello, World from IronPython!
5 IronPython 交互式环境
在终端中直接输入 ipy 并回车,即可进入交互式环境(REPL - Read-Eval-Print Loop),你可以在这里逐行输入 Python 代码并立即看到结果。
$ ipy
IronPython 3.4.0 (3.4.0.4000) on .NET 6.0.0 (X64)
Copyright (c) Microsoft Corporation. All rights reserved.
>>> print("Hello, REPL!")
Hello, REPL!
>>> a = 10
>>> b = 20
>>> a + b
30
>>> exit()
第二部分:核心概念与 Python 语法
与标准 Python 基本一致,因为 IronPython 是 Python 的一个实现。
1 变量与数据类型
Python 是动态类型语言。
# 字符串 name = "Alice" # 整数 age = 30 # 浮点数 height = 1.68 # 布尔值 is_student = False # 类型检查 print(type(name)) # <type 'str'>
2 控制流
# if-elif-else
score = 85
if score >= 90:
print("Grade: A")
elif score >= 80:
print("Grade: B")
else:
print("Grade: C")
# for 循环
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print(f"I like {fruit}")
# while 循环
count = 0
while count < 5:
print(f"Count is {count}")
count += 1
3 函数
使用 def 关键字定义函数。
def greet(name, greeting="Hello"):
"""这是一个文档字符串"""
return f"{greeting}, {name}!"
message = greet("Bob")
print(message) # Hello, Bob!
message2 = greet("Charlie", "Good morning")
print(message2) # Good morning, Charlie!
4 面向对象编程
使用 class 关键字定义类。
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
def bark(self):
return f"{self.name} says: Woof!"
my_dog = Dog("Rex", 5)
print(my_dog.name) # Rex
print(my_dog.bark()) # Rex says: Woof!
第三部分:IronPython 的精髓——与 .NET 交互
这是 IronPython 最强大的部分。
1 导入 .NET 程序集
使用 import 语句,并指定 clr 模块(.NET Common Language Runtime 的缩写)。
import clr
# 导入 System.Windows.Forms 程序集
clr.AddReference("System.Windows.Forms")
# 现在可以导入 .NET 命名空间
from System.Windows.Forms import MessageBox, Application
2 使用 .NET 类型和方法
一旦导入,使用 .NET 类型就像使用 Python 类型一样。
import clr
clr.AddReference("System.Windows.Forms")
from System.Windows.Forms import MessageBox
# 调用 .NET 静态方法
MessageBox.Show("Hello from a .NET MessageBox!", "IronPython Demo")
# 创建 .NET 对象实例
# 注意:构造函数的参数需要放在 [] 中
button = clr.System.Windows.Forms.Button()
button.Text = "Click Me"
3 处理 .NET 集合
.NET 的 List<T> 和 Dictionary<K, V> 可以与 Python 的 list 和 dict 无缝转换。
import clr
clr.AddReference("System.Collections")
from System.Collections.Generic import List
# 创建一个 .NET List of string
net_list = List[str]()
net_list.Add("Python")
net_list.Add("IronPython")
# Python 可以直接迭代它
for item in net_list:
print(item)
# .NET List 可以很容易地转换为 Python list
py_list = list(net_list)
print(py_list) # ['Python', 'IronPython']
4 继承和实现 .NET 接口
IronPython 类可以继承 .NET 类或实现 .NET 接口。
import clr
clr.AddReference("System.Windows.Forms")
from System.Windows.Forms import Form, Label
# 继承 .NET 的 Form 类
class MyForm(Form):
def __init__(self):
super(MyForm, self).__init__()
self.Text = "My IronPython Form"
self.Width = 300
self.Height = 200
# 添加一个 .NET Label 控件
label = Label()
label.Text = "Welcome to IronPython!"
label.Location = clr.System.Drawing.Point(50, 50)
self.Controls.Add(label)
# 运行这个窗体
Application.Run(MyForm())
5 处理事件
为 .NET 对象的事件绑定 Python 函数。
import clr
clr.AddReference("System.Windows.Forms")
from System.Windows.Forms import Button, Application
def button_click(sender, e):
print("Button was clicked!")
button = Button()
button.Text = "Click Me"
button.Click += button_click # 绑定事件处理函数
# 创建一个简单的窗体来显示按钮
form = clr.System.Windows.Forms.Form()
form.Text = "Event Demo"
form.Controls.Add(button)
Application.Run(form)
第四部分:从 C# 调用 IronPython
我们会在一个 C# 主应用程序中嵌入 IronPython 来执行脚本。
1 设置 C# 项目
- 创建一个新的 C# 控制台应用(使用
dotnet new console)。 - 添加
Microsoft.Scripting和IronPython的 NuGet 包。dotnet add package IronPython dotnet add package Microsoft.Scripting
2 执行 Python 脚本文件
创建一个 myscript.py 文件:
# myscript.py
def greet(name):
return f"Hello, {name} from Python script!"
print(greet("C# Host"))
在 C# 代码中执行它:
using System;
using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
public class PythonRunner
{
public static void Main(string[] args)
{
// 创建 Python 引擎
var engine = Python.CreateEngine();
// 执行脚本文件
engine.ExecuteFile("myscript.py");
}
}
3 执行 Python 字符串代码
你也可以直接执行一段 Python 代码字符串。
using System;
using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
public class PythonRunner
{
public static void Main(string[] args)
{
var engine = Python.CreateEngine();
string code = "result = 10 + 20\nprint(f'The result is: {result}')";
engine.Execute(code);
}
}
4 向 Python 传递参数和对象
C# 和 Python 可以互相传递对象。
using System;
using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
public class PythonRunner
{
public static void Main(string[] args)
{
var engine = Python.CreateEngine();
var scope = engine.CreateScope();
// 创建一个 C# 对象并放入 Python 作用域
var person = new Person { Name = "Alice", Age = 30 };
scope.SetVariable("person", person);
// 执行 Python 代码,访问 C# 对象
string code = @"
print(f'Name from C#: {person.Name}')
print(f'Age from C#: {person.Age}')
person.Age = 31 # 修改 C# 对象的属性
";
engine.Execute(code, scope);
// 检查 C# 对象是否被修改
Console.WriteLine($"Back in C#, person's age is now: {person.Age}");
}
}
5 从 Python 获取返回值
通过 ScriptScope 获取 Python 变量的值。
using System;
using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
public class PythonRunner
{
public static void Main(string[] args)
{
var engine = Python.CreateEngine();
var scope = engine.CreateScope();
string code = "def add(a, b): return a + b\nresult = add(5, 7)";
engine.Execute(code, scope);
// 从 Python 作用域中获取变量
dynamic pyResult = scope.GetVariable("result");
Console.WriteLine($"Result from Python: {pyResult}"); // 输出: Result from Python: 12
}
}
第五部分:实战案例
1 案例1:用 IronPython 脚本化 WinForms 界面
目标:创建一个 C# 窗体,窗体上有一个按钮,点击按钮后,执行一个 Python 脚本来动态添加一个新的标签。
-
C# 项目:创建一个 WinForms 应用 (
dotnet new winforms)。 -
添加 NuGet 包:
IronPython和Microsoft.Scripting。 -
窗体设计:在窗体上放一个
Button(名为buttonRunScript) 和一个Panel(名为panelContainer)。 -
创建 Python 脚本 (
add_label.py):# add_label.py def add_label_to_panel(panel, text): # 从 .NET 导入 Label from System.Windows.Forms import Label # 创建标签 label = Label() label.Text = text label.AutoSize = True label.Location = System.Drawing.Point(10, panel.Controls.Count * 25) # 添加到面板 panel.Controls.Add(label) -
C# 按钮点击事件:
using IronPython.Hosting; using Microsoft.Scripting.Hosting; public partial class MainForm : Form { public MainForm() { InitializeComponent(); } private void buttonRunScript_Click(object sender, EventArgs e) { var engine = Python.CreateEngine(); var scope = engine.CreateScope(); // 将 C# 的 panel 对象传递给 Python scope.SetVariable("panel", panelContainer); // 执行脚本 engine.ExecuteFile("add_label.py", scope); // 调用 Python 函数 engine.Execute("add_label_to_panel(panel, 'This label was added by Python!')"); } }
2 案例2:在 C# 应用中嵌入 IronPython 作为脚本引擎
这个案例更通用,适用于任何需要脚本化的应用。
目标:C# 应用程序定义一个 IMathService 接口,Python 脚本实现这个接口,C# 应用加载并调用 Python 的实现。
-
C# 项目:创建一个类库项目,定义接口。
// IMathService.cs public interface IMathService { int Add(int a, int b); } -
Python 脚本实现 (
math_service.py):# math_service.py # 实现 C# 的 IMathService 接口 clr.AddReference("YourAssemblyName") # 替换成你的 C# 类库名 from YourNamespace import IMathService class MyMathService(IMathService): def Add(self, a, b): print(f"Python is adding {a} and {b}") return a + b -
C# 加载和调用代码:
using System; using System.Reflection; using IronPython.Hosting; using Microsoft.Scripting.Hosting; public class ScriptLoader { public IMathService LoadMathService(string scriptPath) { var engine = Python.CreateEngine(); var scope = engine.CreateScope(); // 加载脚本 var source = engine.CreateScriptSourceFromFile(scriptPath); source.Execute(scope); // 获取脚本中定义的类 var pyType = scope.GetVariable("MyMathService"); // 创建 Python 类的实例 dynamic instance = engine.Operations.CreateInstance(pyType); // 将 Python 对象包装成 C# 接口 // 注意:这需要 Python 对象实现了该接口 return (IMathService)instance; } } // 使用示例 var loader = new ScriptLoader(); var mathService = loader.LoadMathService("math_service.py"); int result = mathService.Add(15, 27); Console.WriteLine($"Result from Python service: {result}");
第六部分:资源与进阶
1 官方文档与社区
- IronPython GitHub: https://github.com/IronPython/IronPython (源码、问题追踪、讨论)
- IronPython Documentation: https://ironpython.readthedocs.io/ (官方文档,非常详细)
- Stack Overflow: 搜索
ironpython标签,有大量社区问答。
2 性能考量
- 启动时间:由于需要加载 .NET 运行时和 JIT 编译,IronPython 脚本的启动时间通常比 CPython 慢。
- 执行速度:对于计算密集型任务,C# 的性能通常更高,IronPython 的优势在于胶水逻辑、脚本化和与 .NET 生态的集成,而不是极限性能。
- 优化:对于性能敏感的部分,可以考虑用 C# 编写核心算法,然后通过 IronPython 调用。
3 调试技巧
- 日志:在 Python 代码中使用
print()语句是最简单的调试方法。 - C# 调试:在 C# 中调用
engine.Execute()时,Python 代码出错,会抛出Exception,你可以捕获这个异常来获取错误信息。 - Visual Studio 调试器:高级调试比较困难,因为 Python 代码和 C# 代码运行在不同的上下文中,但你可以结合
print和 C# 的日志系统来定位问题。
希望这份详细的教程能帮助你顺利入门 IronPython!
