我会将“扩展”分为以下几个主要类别,并对每一类进行详细说明:
- 使用 C/C++ 扩展 Python (最核心的扩展方式)
- 使用 C# 扩展 Python (.NET 生态集成)
- 使用 Rust 扩展 Python (现代高性能选择)
- 使用 Cython (Python 的超集)
- 通过子进程调用其他语言程序
- Python 的标准库和第三方库扩展
使用 C/C++ 扩展 Python (最核心的方式)
这是 Python 最经典、最底层的扩展方式,当你需要极致的性能、或者需要调用 Windows 底层 API、或者使用现有的 C/C++ 库时,这是最佳选择。
核心概念
- CPython 解释器:标准的 Python 解释器是用 C 语言编写的,它定义了一套 C 语言 API,允许开发者编写 C 语言代码来创建新的 Python 模块、类型,或者作为 Python 函数的底层实现。
- Python/C API:这是一组函数、宏和类型,让你能编写 C 代码来操作 Python 对象(如整数、列表、字典等),调用 Python 函数,并创建新的 Python 类型。
- 编译和链接:C/C++ 扩展代码需要被编译成动态链接库(在 Windows 上是
.dll文件),Python 才能通过import语句加载它。
实现步骤
- 编写 C/C++ 代码:创建一个 C 文件(
my_module.c),在其中包含你的函数逻辑,并使用 Python/C API 将其暴露给 Python。 - 创建封装文件:创建一个
setup.py脚本,这个脚本是构建过程的入口,它告诉 Python 的构建工具(如setuptools)如何编译你的 C 代码。 - 编译:使用 Python 的
setuptools模块来编译,最简单的方式是运行python setup.py build或更现代的pip install .。
示例
my_module.c
#include <Python.h>
// 一个简单的 C 函数,接收两个整数,返回它们的和
static PyObject* add(PyObject* self, PyObject* args) {
int a, b;
// 解析传入的参数,格式为 "ii" 表示两个整数
if (!PyArg_ParseTuple(args, "ii", &a, &b)) {
return NULL; // 参数解析失败
}
// 创建一个 Python 整数对象并返回
return PyLong_FromLong(a + b);
}
// 模块的方法定义表
static PyMethodDef MyModuleMethods[] = {
{"add", add, METH_VARARGS, "Add two integers"},
{NULL, NULL, 0, NULL} // Sentinel
};
// 模块定义结构体
static struct PyModuleDef myModuleDef = {
PyModuleDef_HEAD_INIT,
"my_module", // 模块名
NULL, // 模块文档
-1, // 模块大小,-表示单模块
MyModuleMethods
};
// 模块初始化函数,Python 解释器会调用它
PyMODINIT_FUNC PyInit_my_module(void) {
return PyModule_Create(&myModuleDef);
}
setup.py
from setuptools import setup, Extension
# 定义你的 C 扩展模块
my_module = Extension(
'my_module', # Python 导入的模块名
sources=['my_module.c'], # 源文件列表
)
setup(
name='My C Extension',
version='1.0',
description='A simple C extension for Python',
ext_modules=[my_module],
)
编译和运行
# 1. 编译 python setup.py build # 2. 安装到当前环境 (推荐) pip install . # 3. 在 Python 中使用 import my_module result = my_module.add(10, 20) print(result) # 输出: 30
优点:
- 性能最高:直接操作内存,没有 Python 解释器的开销。
- 功能最强:可以访问任何 C/C++ 库和 Windows API。
- 生态兼容:绝大多数高性能的 Python 库(如 NumPy, Pandas)的底层都是 C/C++ 扩展。
缺点:
- 开发复杂:需要熟悉 C/C++ 和 Python/C API,容易出错(内存管理、引用计数等)。
- 平台相关:代码需要针对不同平台(Windows, Linux, macOS)进行编译。
使用 C# 扩展 Python (.NET 生态集成)
如果你的项目需要与 .NET 生态(如 ASP.NET, Entity Framework)深度集成,或者想利用 C# 的强大功能,可以使用 pythonnet 库。
核心概念
pythonnet:一个开源的包,它充当 Python 和 .NET 运行时之间的桥梁。- CLR (Common Language Runtime):.NET 的核心运行时。
pythonnet允许你在 Python 进程中加载 CLR,从而调用 .NET 程序集(.dll)。
实现步骤
- 安装
pythonnet:pip install pythonnet - 编写 C# 代码:创建一个 C# 类库项目,编译成
.dll文件。 - 在 Python 中调用:使用
clr模块加载 C# 的 DLL,然后像使用普通 Python 对象一样使用 C# 的类和方法。
示例
C# 代码 (MyMathLibrary.cs)
using System;
public class MyMathLibrary
{
public static int Add(int a, int b)
{
return a + b;
}
}
编译这个 C# 文件成一个 DLL (MyMathLibrary.dll)。
Python 代码
import clr # 指向你的 C# DLL 的路径 clr.AddReference(r"C:\path\to\your\MyMathLibrary.dll") # 导入 C# 的命名空间和类 from MyMathLibrary import MyMathLibrary # 直接调用 C# 的静态方法 result = MyMathLibrary.Add(100, 200) print(result) # 输出: 300
优点:
- 无缝集成 .NET:可以轻松使用 .NET 生态中的库和框架。
- 开发体验好:如果你熟悉 C#,可以享受其强大的工具链(如 Visual Studio)。
- 托管代码:避免了 C/C++ 的手动内存管理。
缺点:
- 性能:性能不如 C/C++ 扩展,因为存在 Python 和 CLR 之间的互操作开销。
- 依赖 .NET Runtime:目标机器需要安装相应的 .NET 运行时(.NET Framework 或 .NET Core/5+)。
使用 Rust 扩展 Python (现代高性能选择)
Rust 是一门注重安全、速度和并发的系统编程语言,近年来,它成为了扩展 Python 的一个非常热门的选择。
核心概念
PyO3:一个 Rust 库,它允许你将 Rust 代码编译成 Python 可以导入的模块,它提供了安全且高效的 Python/C API 绑定。maturin:一个构建工具,专门用于构建和打包基于 PyO3 的 Rust 扩展,它简化了setup.py的编写和编译过程。
实现步骤
- 安装 Rust 和
maturin:pip install maturin - 创建项目:
maturin new my_rust_module - 编写 Rust 代码:在
src/lib.rs中使用pyfunction等宏来暴露函数。 - 编译和安装:
maturin develop(用于开发) 或maturin build --release(用于发布)。
示例
src/lib.rs
use pyo3::prelude::*;
#[pyfunction]
fn add_numbers(a: i64, b: i64) -> i64 {
a + b
}
// 这个宏定义了 Python 模块
#[pymodule]
fn my_rust_module(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(add_numbers, m)?)?;
Ok(())
}
编译和运行
# 1. 进入项目目录 cd my_rust_module # 2. 开发模式编译和安装 maturin develop # 3. 在 Python 中使用 import my_rust_module result = my_rust_module.add_numbers(1000, 2000) print(result) # 输出: 3000
优点:
- 高性能:性能媲美 C/C++ 扩展。
- 内存安全:Rust 的所有权系统在编译时就能避免大部分内存错误(如空指针、数据竞争)。
- 优秀的工具链:
cargo提供了顶级的包管理和构建体验。
缺点:
- 学习曲线:Rust 的所有权和生命周期概念对初学者有一定挑战。
- 生态系统相对较新:虽然发展迅速,但可用的第三方库数量还不及 C++。
使用 Cython (Python 的超集)
Cython 是一个静态编译器,它将 Python 的超集代码(可以包含 C 类型声明)编译成优化的 C 代码,然后再编译成 Python 扩展模块。
核心概念
.pyx文件:编写 Cython 代码的文件,它语法上兼容 Python,并增加了 C 的类型声明。- 类型声明:通过为变量和函数参数添加 C 类型(如
cdef int a),Cython 可以生成高效的 C 代码,避免 Python 的动态类型开销。
实现步骤
- 安装 Cython:
pip install cython - 编写
.pyx文件:编写带有类型声明的 Python 代码。 - 创建
setup.py:使用Extension指定.pyx文件。 - 编译:使用
setup.py或pip进行编译。
示例
my_cython_module.pyx
# 声明 C 类型的函数
def add_cython(int a, int b):
# a 和 b 在这里是 C 整数,运算速度极快
cdef int result = a + b
return result
# 也可以声明 Python 类型的函数,性能会差一些
def add_python(a, b):
return a + b
setup.py
from setuptools import setup, Extension
from Cython.Build import cythonize
ext_modules = [
Extension("my_cython_module", sources=["my_cython_module.pyx"])
]
setup(
name="My Cython Module",
ext_modules=cythonize(ext_modules)
)
编译和运行
# 编译和安装 pip install . # 在 Python 中使用 import my_cython_module print(my_cython_module.add_cython(10, 20)) # 输出: 30
优点:
- 开发效率高:语法接近 Python,比纯 C/C++ 容易上手。
- 性能显著提升:通过类型声明可以获得接近 C 的性能。
- 无缝集成:可以轻松调用 C/C++ 库。
缺点:
- 不是纯 Python:引入了额外的编译步骤,不再是“纯”的脚本语言。
- 调试复杂:编译后的 C 代码难以调试。
通过子进程调用其他语言程序
这是一种最简单、最“非侵入式”的扩展方式,你的主程序是 Python,当你需要执行其他语言的代码时,通过 subprocess 模块启动一个外部进程。
示例
import subprocess
# 调用一个用 Node.js 编写的脚本
node_script = "console.log('Hello from Node.js!');"
result = subprocess.run(['node', '-e', node_script], capture_output=True, text=True)
print("Node.js output:", result.stdout)
# 调用一个用 PowerShell 编写的脚本
ps_script = "Write-Output 'Hello from PowerShell!'"
result = subprocess.run(['powershell', '-Command', ps_script], capture_output=True, text=True)
print("PowerShell output:", result.stdout)
优点:
- 实现简单:不需要学习复杂的 API,只需调用命令行。
- 完全解耦:Python 和其他语言程序运行在独立的进程中,互不影响。
- 利用现有工具:可以复用任何可以命令行调用的工具或脚本。
缺点:
- 性能开销大:进程的创建和销毁、进程间通信(IPC)都有很高的成本。
- 通信复杂:传递复杂数据结构(如对象、列表)需要序列化和反序列化(如 JSON)。
- 异步困难:管理多个子进程的并发和异步任务比较繁琐。
Python 的标准库和第三方库扩展
这通常不是指“扩展 Python 语言本身”,而是指“扩展 Python 的功能”,Python 拥有极其丰富的库生态,几乎可以实现所有常见任务。
- 标准库:
os,sys,socket,threading,json等,开箱即用。 - 科学计算:
NumPy(高性能数组),SciPy(科学算法),Pandas(数据分析)。 - Web 开发:
Django(全栈框架),Flask(微框架),FastAPI(现代高性能框架)。 - 自动化与 Windows 特定:
pywin32:提供对 Windows API 的直接访问,可以操作 COM 对象、注册表、系统服务等。ctypes:Python 的外部函数库,可以方便地调用 DLL 中的函数。wmi:通过 WMI (Windows Management Instrumentation) 管理 Windows 系统。
总结与选择建议
| 扩展方式 | 性能 | 开发难度 | 适用场景 | 依赖 |
|---|---|---|---|---|
| C/C++ 扩展 | ⭐⭐⭐⭐⭐ (最高) | ⭐⭐ (最难) | 极致性能、底层操作、调用现有 C/C++ 库 | C 编译器 |
| Rust 扩展 | ⭐⭐⭐⭐⭐ (最高) | ⭐⭐⭐ | 高性能、内存安全、现代系统编程 | Rust, maturin |
| Cython | ⭐⭐⭐⭐ (很高) | ⭐⭐⭐ | 在 Python 语法下获得高性能 | Cython, C 编译器 |
| C# (.NET) | ⭐⭐⭐ (中等) | ⭐⭐ | 深度集成 .NET 生态 | .NET Runtime |
| 子进程 | ⭐ (最低) | ⭐ (最简单) | 快速调用外部工具、解耦任务 | 无 (OS 级别) |
| Python 库 | ⭐⭐⭐ (取决于库) | ⭐ (最简单) | 绝大多数应用场景 | pip |
如何选择?
- 追求极致性能,且不畏惧 C/C++ 的复杂性:选择 C/C++ 扩展。
- 追求极致性能,同时希望内存安全和现代开发体验:选择 Rust 扩展。
- 希望在接近 Python 的语法下获得显著的性能提升:选择 Cython。
- 项目需要与 .NET 生态(如 WPF, ASP.NET Core)深度集成:选择 C# 扩展。
- 只是偶尔需要调用一个独立的、命令行工具:选择 子进程。
- 绝大多数情况下的开发:优先使用 Python 的标准库和第三方库,它们已经覆盖了绝大部分需求,只有在现有库无法满足时,才考虑上述扩展方式。
