杰瑞科技汇

如何在Windows上扩展Python功能?

我会将“扩展”分为以下几个主要类别,并对每一类进行详细说明:

  1. 使用 C/C++ 扩展 Python (最核心的扩展方式)
  2. 使用 C# 扩展 Python (.NET 生态集成)
  3. 使用 Rust 扩展 Python (现代高性能选择)
  4. 使用 Cython (Python 的超集)
  5. 通过子进程调用其他语言程序
  6. 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 语句加载它。

实现步骤

  1. 编写 C/C++ 代码:创建一个 C 文件(my_module.c),在其中包含你的函数逻辑,并使用 Python/C API 将其暴露给 Python。
  2. 创建封装文件:创建一个 setup.py 脚本,这个脚本是构建过程的入口,它告诉 Python 的构建工具(如 setuptools)如何编译你的 C 代码。
  3. 编译:使用 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)。

实现步骤

  1. 安装 pythonnetpip install pythonnet
  2. 编写 C# 代码:创建一个 C# 类库项目,编译成 .dll 文件。
  3. 在 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 的编写和编译过程。

实现步骤

  1. 安装 Rust 和 maturinpip install maturin
  2. 创建项目maturin new my_rust_module
  3. 编写 Rust 代码:在 src/lib.rs 中使用 pyfunction 等宏来暴露函数。
  4. 编译和安装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 的动态类型开销。

实现步骤

  1. 安装 Cythonpip install cython
  2. 编写 .pyx 文件:编写带有类型声明的 Python 代码。
  3. 创建 setup.py:使用 Extension 指定 .pyx 文件。
  4. 编译:使用 setup.pypip 进行编译。

示例

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 的标准库和第三方库,它们已经覆盖了绝大部分需求,只有在现有库无法满足时,才考虑上述扩展方式。
分享:
扫描分享到社交APP
上一篇
下一篇