From Python to Rust: A Developer’s Journey of Performance Awakening
Introduction
As a developer, have you ever found yourself deeply immersed in the gentle embrace of Python? Its concise syntax, rich libraries, and rapid development efficiency seem to solve all problems. However, when your project starts handling gigabytes of data and your API faces high concurrency requests, the limitations of Python begin to surface.
This article shares the journey of a developer transitioning from a “devout Python believer” to a “bilingual Rust user.” This is not an article urging you to abandon Python, but rather to help you understand when to use Python, when to use Rust, and how to perfectly combine the two.
1. Performance Bottlenecks: The Beginning of the Problem
1.1 Encountering Performance Dilemmas
The story begins with a seemingly simple task: processing a CSV file of several gigabytes. The author tried various Python optimization strategies:
- Optimizing loop logic
- Using generators to reduce memory usage
- Switching to Pandas for data processing
However, the script’s runtime remained unacceptable. This prompted the author to ponder, “Why is my Python code so slow?”
1.2 First Encounter with Rust
During the search for answers, the name Rust frequently appeared. The developer community was discussing its three main features:
- Extreme Performance: Close to C/C++ execution speed
- Memory Safety: Most memory errors can be detected at compile time
- Precise Control: Allows developers to master every detail of program execution
Initially, the author thought this was just hype. But one experiment changed everything.
2. The First Rust Experiment: Shocking Results
2.1 Simple Comparison Test
The author decided to rewrite a simple function from the Python script in Rust: reading a CSV file and counting unique values.
Python Implementation:
# Python implementation: concise and intuitive
data = set()
for line in open('data.csv'):
data.add(line.strip()) # Remove whitespace and add to set
print(len(data)) # Output the number of unique values
This code took about 20 seconds to run.
Rust Implementation Challenge:
The Rust implementation was much more complex. The author needed to:
- Explicitly declare variable types
- Handle potential error cases
- Understand ownership and borrowing mechanisms
- Manage memory allocation
The first five compilations failed. But when the code finally ran, it took less than 2 seconds.
2.2 The Essence of Performance Differences
This tenfold performance improvement was not coincidental. The underlying reasons include:
- Compiled vs Interpreted: Rust code is compiled into machine code for direct execution, while Python requires an interpreter to execute line by line
- Memory Management: Rust’s zero-cost abstractions and precise memory control
- Concurrency Safety: Rust’s type system ensures thread safety, allowing full utilization of multi-core CPUs
3. Application in Real Projects: Image Processing API
3.1 Real-World Scenario
The author was building a Python API using FastAPI, which included image upload, scaling, and storage to AWS. This module performed poorly when processing large batches of images:
- Long response times
- High memory usage
- Occasional memory errors leading to crashes
3.2 Rust Refactoring Solution
The author only rewrote the core image processing module, retaining the FastAPI framework and other Python code. The results were surprising:
- Performance Improvement: Running speed increased nearly tenfold
- Memory Optimization: Memory usage significantly reduced
- Stability Improvement: No more random memory errors
3.3 Key Takeaway: Compile-Time Guarantees
The most important takeaway was not performance, but confidence. Rust’s compiler captures almost all potential issues before the code runs:
- Memory leaks
- Null pointer dereferences
- Data races
- Type mismatches
Errors in Python that only surface at runtime cannot even compile in Rust.
4. Python Still Has Its Value
4.1 Comparison of Development Efficiency
The author emphasizes that he has not abandoned Python. In the following scenarios, Python remains the first choice:
- Rapid Prototyping: Validate an idea in minutes
- Automation Scripts: Concise syntax is suitable for writing operational tools
- AI and Data Science: Rich ecosystem (TensorFlow, PyTorch, Pandas, etc.)
- Glue Code: Connecting different systems and services
In contrast, implementing the same functionality in Rust could take hours.
4.2 Differences in Abstraction Levels
The author used a vivid analogy:
Python is like an automatic car—easy to use, just get in and drive
Rust is like a manual sports car—requires understanding every detail, but offers powerful performance
Python hides many low-level details, allowing you to focus on business logic. Rust, on the other hand, requires you to understand:
- How memory is allocated and released
- Who owns the data
- The lifespan of references
This “forced thinking” actually made the author a better developer.
4.3 Skill Transfer Effects
After learning Rust, the author found that the quality of his Python code also improved:
- More attention to resource management
- Reduced unnecessary copies
- Clearer understanding of program execution flow
- Easier identification of performance bottlenecks
5. Best Practices: Python + Rust Hybrid Architecture
5.1 Decision Tree for Language Selection
After several months of practice, the author summarized a set of practical decision principles:
Scenarios for Using Python:
- Need for rapid development and iteration
- Performance requirements are not high
- Dependent on specific libraries in the Python ecosystem
- Team members are more familiar with Python
Scenarios for Using Rust:
- Performance-critical paths (CPU-intensive tasks)
- Need to ensure memory safety
- System-level programming
- Need precise control over resource usage
5.2 Hybrid Development Solutions
The most powerful solution is to combine both:
- Build the application framework with Python: API layer, business logic, database interaction
- Implement performance-critical modules with Rust: Data processing, image/video encoding/decoding, encryption algorithms
- Connect the two via FFI or PyO3
Simple Example Using PyO3
Rust Side (lib.rs):
use pyo3::prelude::*;
/// High-performance data processing function implemented in Rust
#[pyfunction]
fn process_large_data(data: Vec<String>) -> PyResult<usize> {
// Rust's efficient processing logic
let unique_count = data.iter()
.map(|s| s.trim()) // Remove whitespace characters
.collect::<std::collections::HashSet<_>>() // Collect into HashSet for deduplication
.len(); // Return the number of unique values
Ok(unique_count)
}
/// Python module definition
#[pymodule]
fn rust_module(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(process_large_data, m)?)?;
Ok(())
}
Python Side Call:
import rust_module
# Prepare a large dataset
large_dataset = ["item1", "item2", "item1", "item3"] * 1000000
# Call the high-performance function implemented in Rust
unique_count = rust_module.process_large_data(large_dataset)
print(f"Number of unique values: {unique_count}")
5.3 Example of Project Architecture
Taking a Web API as an example:
┌─────────────────────────────────────┐
│ FastAPI / Flask (Python) │ ← API routing, authentication, business logic
├─────────────────────────────────────┤
│ Middleware (PyO3 / ctypes) │ ← Bridge between Python and Rust
├─────────────────────────────────────┤
│ Performance-Critical Module (Rust) │ ← Image processing, data parsing, encryption
└─────────────────────────────────────┘
│
▼
Database / Cache / External Services
6. Suggestions for Learning Rust
6.1 Mindset Adjustment
Transitioning from Python to Rust is not an overnight process. The author’s suggestions include:
- Expect Compilation Errors: Frequent compilation failures in the early stages are normal
- Embrace the Compiler: Treat the compiler’s error messages as your best teacher
- Take Small Steps: Start by rewriting small functions and gradually accumulate experience
- Don’t Force It: Not all code needs to be rewritten in Rust
6.2 Recommended Learning Path
- Basic Syntax: Ownership, borrowing, lifetimes
- Common Data Structures: Vec, HashMap, Option, Result
- Error Handling: The ? operator and custom error types
- Concurrent Programming: Threads, channels, Arc, Mutex
- Practical Projects: Choose a real problem to solve with Rust
6.3 Common Pitfalls
Pitfall 1: Over-Optimization
Don’t get caught up in performance optimization from the start. Get the code running first, then optimize hotspots based on profiling results.
Pitfall 2: Fighting the Compiler
If the compiler rejects your code, it’s likely a design issue, not that the compiler is too strict.
Pitfall 3: Ignoring the Ecosystem
Rust’s library ecosystem is not as mature as Python’s, and certain areas may lack ready-made solutions.
7. Core Insights
At the end of the article, the author shares the most important cognitive shift:
I used to believe that one language could solve all problems.
After learning Rust, I realized that every language has its purpose.
Python gives you freedom, while Rust gives you control.
When you master both, you no longer code blindly—you begin to truly understand everything happening behind the screen.
This is not just about tool selection, but about upgrading your mindset:
- From “as long as it runs” to “understanding the principles”
- From “quick implementation” to “long-term maintenance”
- From “single tool” to “toolbox thinking”
Conclusion
Python and Rust are not mutually exclusive; they are complementary partners.
Advantages of Python:
- Fast development speed
- Gentle learning curve
- Rich ecosystem
- Suitable for rapid iteration and prototyping
Advantages of Rust:
- Performance close to C/C++
- Memory safety guarantees
- Concurrency-friendly
- Suitable for performance-critical scenarios
Best Practices:
- Use Python to build application skeletons and business logic
- Use Rust to optimize performance bottlenecks
- Seamlessly integrate using tools like PyO3
- Select the appropriate language based on specific scenarios
For developers learning Rust, remember: the value of learning Rust lies not only in mastering a new language but in gaining a new programming mindset. Even if you ultimately do not use Rust extensively in production, it will make you a better programmer.
Do not fear the compiler’s strictness; it is helping you write safer, more reliable code. Every compilation error is a learning opportunity.
References
- I Used Python for Everything — Until I Discovered Rust: https://medium.com/@kirantechblog/i-used-python-for-everything-until-i-discovered-rust-5aed88c2a78d
Book Recommendations
The book “The Rust Programming Language” (Chinese version, second edition) is an authoritative learning resource written by the Rust core development team and translated by members of the Chinese Rust community. It is suitable for all software developers who wish to evaluate, get started, improve, and research the Rust language, and is considered essential reading for Rust development work.
This book introduces the basic concepts of the Rust language to unique practical tools, covering advanced concepts such as ownership, traits, lifetimes, and safety guarantees, as well as practical tools like pattern matching, error handling, package management, functional features, and concurrency mechanisms. The book includes three complete project development case studies, guiding readers from zero to developing practical Rust projects.
Notably, this book has been updated to the Rust 2021 version, meeting the systematic learning needs of beginners and serving as a reference guide for experienced developers, making it the best entry point for building solid Rust skills.
Recommended Reading
-
Rust: The Performance King Sweeping C/C++/Go?
-
Looking at C++ from the Perspective of a Rust Developer: Revealing Pros and Cons
-
Rust vs Zig: The Battle of Emerging System Programming Languages
-
Essential Design Patterns for Asynchronous Programming in Rust: Enhance Your Code’s Performance and Maintainability