Hey everyone! Today we’re going to talk about something exciting, Python slow? Not at all!
I have always thought that Python is a great language, it’s clean and elegant, and the development efficiency is top-notch. But when it comes to performance-sensitive areas, the speed can really make you question life. Don’t worry, today I’m going to teach you a trick to make your Python code fly, and that is—Rust!
That’s right, it’s the Rust known for its high performance and safety! I know, when Rust is mentioned, many people might feel overwhelmed, thinking it’s too hard to learn. But don’t panic, the method I’m teaching you today doesn’t require you to become a Rust expert, yet it will make your Python code soar.
My discovery: The combination of Python and Rust is simply a match made in heaven. Python handles rapid development while Rust optimizes performance, perfect!
The key is to write Python extension modules in Rust!
Sounds a bit fancy, right? Actually, it’s not that complicated. Let me give you an example. Suppose you need a function to perform complex mathematical operations on a huge list. Implementing it in pure Python would be painfully slow. At this point, writing a function in Rust and having Python call it can increase efficiency by several orders of magnitude!
Alright, let’s look at some code. I’ll demonstrate with a simple example:
First, we write a simple function in Rust to calculate the sum of squares of all elements in a list.
// src/lib.rs
#[no_mangle]
pub extern "C" fn sum_of_squares(arr: *const i32, len: usize) -> i32 {
let mut sum = 0;
let arr_slice = unsafe { std::slice::from_raw_parts(arr, len) };
for &x in arr_slice {
sum += x * x;
}
sum
}
This piece of code is nothing special; it simply defines a sum_of_squares function in Rust that takes a pointer to an array of i32
type and its length, then computes the sum of squares and returns the result as i32
.
Next, we need to configure the Cargo.toml file to tell Rust to compile this library into a C-compatible dynamic library.
[package]
name = "my_rust_module"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
Next, compile this Rust code.
cargo build --release
After compilation, you will find a file named libmy_rust_module.so (on Linux) or my_rust_module.dll (on Windows) generated in the target/release directory. This is the dynamic library we need.
Now, let’s return to Python and write some code to call it:
# main.py
import ctypes
import time
import random
# Load Rust dynamic library
# Replace so with dll on Windows
_rust_lib = ctypes.CDLL('./target/release/libmy_rust_module.so')
# Define the argument and return types for the Rust function
_rust_lib.sum_of_squares.argtypes = [ctypes.POINTER(ctypes.c_int), ctypes.c_size_t]
_rust_lib.sum_of_squares.restype = ctypes.c_int
def rust_sum_of_squares(arr):
# Convert Python list to ctypes array
arr_ptr = (ctypes.c_int * len(arr))(*arr)
# Call Rust function
return _rust_lib.sum_of_squares(arr_ptr, len(arr))
def python_sum_of_squares(arr):
sum_val = 0
for x in arr:
sum_val += x * x
return sum_val
if __name__ == '__main__':
arr = [random.randint(1, 100) for _ in range(1000000)]
start_time = time.time()
rust_result = rust_sum_of_squares(arr)
end_time = time.time()
print(f"Rust result: {rust_result}, Time taken: {end_time - start_time:.6f} seconds")
start_time = time.time()
python_result = python_sum_of_squares(arr)
end_time = time.time()
print(f"Python result: {python_result}, Time taken: {end_time - start_time:.6f} seconds")
As you can see, I used the ctypes
module to load the Rust-compiled dynamic library and defined the argument and return types for the Rust function. Then, in Python, we can directly call the Rust function just like a regular Python function.
My advice: Don’t think Rust is too complicated; as long as you master the basic Rust syntax and combine it with the ctypes
module, you can easily bring Rust’s high performance into your Python projects. Don’t consider yourself an outsider.
Pitfall record: Make sure to write the path to the dynamic library correctly, and ensure that Rust’s data types correspond to Python’s data types, or you might find yourself in trouble.
Run the above code, and you’ll find that the Rust version is several times, even dozens of times faster than the Python version! The feeling is absolutely fantastic.
Thought-provoking question: Why is Rust’s computation speed so much faster than Python’s? Besides the characteristics of the language itself, are there other reasons?
My experience is: If your Python code has performance bottlenecks, don’t hesitate, just rewrite it in Rust. You don’t have to refactor the entire project; just optimize the most time-consuming parts with Rust, and the effect will be immediate!
Of course, I’m not saying Python is inadequate; it’s just that in certain specific scenarios, Rust’s performance advantages are indeed significant. What we need to do is to make good use of different tools, leveraging their respective strengths, and don’t get stuck in one direction. Trying different approaches is always a good idea.
Rust Accelerating Python: The High-Performance Future
To summarize, today I taught you how to speed up Python code using Rust. The core idea is to write extension modules in Rust and then call them from Python. Although this requires you to master some basic Rust knowledge, the performance improvements are absolutely worth the effort.
In the future, mixed programming will become increasingly common. Python + Rust is definitely a combination worth mastering. Stop complaining about Python being slow; try the method I taught you today and let your Python code fly!