杰瑞科技汇

Python扩展如何开发与集成?

Of course! The term "Python extension" can refer to a few different things, but most commonly it means code written in another language (like C or C++) that can be imported and used directly in Python.

Python扩展如何开发与集成?-图1
(图片来源网络,侵删)

This is a powerful technique used to:

  • Speed up critical code sections: For computationally intensive tasks (like numerical computations or image processing), C/C++ can be significantly faster.
  • Access low-level system features: Interact with hardware or operating system functionalities that are not accessible from pure Python.
  • Integrate existing C/C++ libraries: If you have a high-performance library written in C, you can wrap it for Python use without rewriting it.

Let's break down the most common types and how to create them.


C Extension Modules (The Classic Approach)

This is the traditional way to extend Python. You write C code that adheres to the Python C API, which acts as a bridge between your C code and the Python interpreter.

How it Works

The Python interpreter can load a dynamically shared library (.so on Linux, .pyd on Windows, .dylib on macOS). Your C code must expose functions that the Python interpreter can call. The Python.h header file provides the necessary functions and macros to convert between Python objects (like lists, strings) and C types (like int, char*).

Python扩展如何开发与集成?-图2
(图片来源网络,侵删)

Example: A Simple C Extension

Let's create a C extension that adds two numbers.

Step 1: Write the C code (add.c)

#include <Python.h>
// This is the function that will be called from Python
static PyObject* add_numbers(PyObject* self, PyObject* args) {
    long a, b;
    // Parse arguments from the Python tuple. "ll" means two longs.
    if (!PyArg_ParseTuple(args, "ll", &a, &b)) {
        return NULL; // Error handling is done by PyArg_ParseTuple
    }
    // Create the result as a Python Long object
    long result = a + b;
    return PyLong_FromLong(result);
}
// This is the module definition. It lists the functions available in the module.
static PyMethodDef AddMethods[] = {
    {"add", add_numbers, METH_VARARGS, "Add two integers"},
    {NULL, NULL, 0, NULL} // Sentinel
};
// This is the module definition structure.
static struct PyModuleDef addmodule = {
    PyModuleDef_HEAD_INIT,
    "addmodule", // Module name
    NULL,        // Module documentation
    -1,
    AddMethods
};
// This is the function that gets called when the module is imported.
PyMODINIT_FUNC PyInit_addmodule(void) {
    return PyModule_Create(&addmodule);
}

Step 2: Create a setup.py file This script tells Python's build system how to compile your C code into a module.

from setuptools import setup, Extension
# Define the extension module
my_module = Extension(
    'addmodule',  # The name of the module after compilation
    sources=['add.c'] # The list of C source files
)
setup(
    name='MyAddModule',
    version='1.0',
    description='A simple C extension for adding numbers',
    ext_modules=[my_module]
)

Step 3: Build and Install Open your terminal in the same directory as the files and run:

Python扩展如何开发与集成?-图3
(图片来源网络,侵删)
python setup.py build
python setup.py install

Or, the modern way:

pip install .

Step 4: Use it in Python Now you can import and use your C extension just like any other Python module.

>>> import addmodule
>>> addmodule.add(5, 10)
15
>>> addmodule.add(-100, 250)
150

The Modern & Recommended Approach: Cython

Cython is a superset of the Python language that allows you to add static C type definitions. You write .pyx files that look like Python, and Cython compiles them into highly optimized C extensions. This is much easier and safer than writing raw C extensions.

How it Works

Cython translates your .pyx code into C code, which is then compiled into a Python extension module. It handles all the complex C API boilerplate for you.

Example: A Simple Cython Extension

Let's recreate the same adder with Cython.

Step 1: Write the Cython code (add_cython.pyx) This looks almost like Python, but with type annotations for performance.

# Declare the function with C-style type hints
def add_cython(long a, long b):
    return a + b

Step 2: Create a setup.py file The setup is very similar, but you use cythonize to process the .pyx file.

from setuptools import setup, Extension
from Cython.Build import cythonize
# Define the extension module
my_module = Extension(
    'add_cython', # Module name
    sources=['add_cython.pyx'] # The Cython source file
)
setup(
    name='MyCythonAddModule',
    version='1.0',
    ext_modules=cythonize(my_module) # Use cythonize to compile the .pyx file
)

Step 3: Build and Install You need Cython installed first: pip install cython Then, build and install as before:

python setup.py build
python setup.py install

or

pip install .

Step 4: Use it in Python

>>> import add_cython
>>> add_cython.add_cython(5, 10)
15
>>> add_cython.add_cython(-100, 250)
150

Why Cython is better:

  • Easier Syntax: You work with a Python-like language, not the complex C API.
  • Automatic Error Handling: Cython generates code that raises proper Python exceptions.
  • Seamless Python Object Handling: It's much easier to work with Python lists, dictionaries, etc., from Cython.
  • Debugging: You can use standard Python debuggers on your .pyx code.

Other Types of "Extensions"

It's useful to know the other meanings of the term.

a. Python Sub-Interpreters

This is a more advanced feature. A Python process can have multiple "sub-interpreters." These are isolated execution environments that share the same process but have their own global namespaces (modules, variables, etc.). This is used in applications like mod_wsgi for web servers to isolate different applications.

b. Python C-API Embedding

This is the reverse of a C extension. Instead of calling C from Python, you embed the Python interpreter inside a C/C++ application. This allows your C program to execute Python scripts, use Python libraries, and leverage Python's dynamic features. This is how applications like Blender, Maya, and games integrate scripting capabilities.


Summary: Which one should you use?

Method Use Case Pros Cons
C Extension Maximum performance, low-level system access, wrapping existing C libraries. Ultimate performance, full control. Very complex, error-prone, hard to debug, non-portable code.
Cython Highly Recommended. Optimizing critical Python code, wrapping C/C++ libraries. Easier than C, Python-like syntax, great performance, good debugging. Requires an extra compilation step. Not as low-level as raw C.
ctypes Calling simple, external shared libraries (.dll, .so). Built-in to Python, no compilation needed. Verbose, type checking is manual, not as efficient as Cython for complex types.
CFFI Calling C libraries from Python. Can be used at runtime or build time. Modern, supports C99, good performance, can be more flexible than Cython. Can be more complex to set up than Cython for pure Python extensions.

For almost all use cases, start with Cython if you need to speed up Python code or wrap C/C++ libraries. It provides the best balance of performance, ease of use, and safety. Only resort to writing raw C extensions if you have a very specific, performance-critical need and are an expert in the Python C API.

分享:
扫描分享到社交APP
上一篇
下一篇