If you’ve ever wanted to combine the power of Rust with the interactive goodness of Jupyter Notebooks, you’re in the right place. Maybe you’re tired of me every time you want to test a snippet, learn Rust more interactively, or just have a crazy idea.
Most people think Jupyter is just for Python and data science stuff, but apparently you can run Rust in one too.
In this tutorial, we’ll take a look at:
Friendly disclaimer: This tutorial assumes you know the basics of both Rust and Jupyter. If you break something, it’s on you, man 🙂 .
So without further ado, let’s jump in.
What is EvCxR?
EvCxR (called “evaluator” to the horror of my fellow linguists) is a Rust REPL and Jupyter kernel. This is basically magic that lets you run Rust code interactively in a Jupyter notebook instead of the traditional compile run debug cycle.
The name stands for “Evaluation Context for Rust”, and it is an open source project actively maintained on GitHub. Here are some of the things that make this appallingly named device absolutely brilliant:
Interactive development: This lets you test pieces of rust without building a full project 🧪
Prototyping: You can test ideas quickly before committing to a full implementation 💡
Data Visualization: And yes, you can also create charts with Rust (more on that later) 📊
How to install the Rust Jupyter kernel
Conditions
Before we dive into the installation, make sure you’ve configured these:
Linux system: Or at least, the Windows Subsystem for Linux (a small note below for Windows users).
Rust Tool Chain: can get from rustup.rs If you haven’t already
Jupiter: install via pipe –
pip install jupyterPatience: This may take a minute or two
Once you get it all, we can be rusty (pun intended).
Note: If you’re using Windows, you’ll need to do a little extra work to get started. Here’s a quick rundown:
Download and run the installer.
select “Desktop Development with C++”
Install it (it’s big, ~5 GB)
Step 1: Install EvCxR.
Open your terminal and run this command:
cargo install evcxr_jupyter
Now go grab a cup of joe ☕. This will take a few minutes as Cargo downloads and compiles everything. And don’t panic if it’s stuck. Rust compilation is thorough but not particularly fast.
If you get an error about missing system libraries, you may need to install some dependencies. On Ubuntu/Debian, try:
sudo apt install jupyter-notebook jupyter-core python-ipykernel
sudo apt install cmake
On macOS with Homebrew:
brew install cmake jupyter
Step 2: Install Jupyter Kernel
After the installation is finished, you will need to register the EvCxR kernel with Jupyter:
evcxr_jupyter --install
You should see output that finally looks something like this:
Installation complete
Step 3: Launch Jupyter and create a Rust notebook
Let’s examine your child. Fire Jupiter:
jupyter notebook
Your browser should open automatically (if it doesn’t, copy the URL from Terminal).
In the Jupyter interface:
Click new Top right
select rust from the dropdown (or “evcxr” depending on your version)
A new notebook opens.
Welcome to Interactive Rust! 🦀
Step 4: Write your first Rust code.
Let’s start with a classic:
println!("Hello my fellow Rustaceans! 🦀");
hit Shift + Enter To operate the cell. You should see the output below the cell. Simple as that.
Note that the notebook executes the code at the top level, so you don’t need to wrap it main() function if you still want to do this, you have to call it like this:
fn main(){
println!("Hello my fellow Rustaceans! 🦀");
}
//Calling the function
main()
Now let’s try something more interesting:
fn fibonacci(n: u32) -> u32 {
match n {
0 => 0,
1 => 1,
_ => fibonacci(n - 1) + fibonacci(n - 2)
}
}
for i in 0..10 {
println!("fibonacci({}) = {}", i, fibonacci(i));
}
Run it and watch the Fibonacci sequence appear.
fibonacci(0) = 0
fibonacci(1) = 1
fibonacci(2) = 1
fibonacci(3) = 2
fibonacci(4) = 3
fibonacci(5) = 5
fibonacci(6) = 8
fibonacci(7) = 13
fibonacci(8) = 21
fibonacci(9) = 34
Easy tips and tricks
Functions aren’t the only things that behave differently when using Rust in a notebook. Here are some other things you may want to keep in mind:
Variations persist between cells.
Unlike traditional Rust compilation, variables you define in one cell stick to subsequent cells:
let mut counter = 0;
Then in the next cell:
counter += 1;
println!("Counter: {}", counter);
The output will be:
Counter: 1
It’s great for creating complex step-by-step examples.
You can use outdoor crates.
Add dependencies with :dep Command in a cell:
:dep serde = { version = "1.0", features = ("derive") }
:dep serde_json = "1.0"
Then use them normally in the next:
use serde::{Serialize, Deserialize};
#(derive(Serialize, Deserialize, Debug))
struct Person {
name: String,
age: u32,
}
let person = Person {
name: "Amina".to_string(),
age: 24,
};
let json = serde_json::to_string(&person).unwrap();
println!("{}", json);
Output:
{"name":"Amina","age":24}
Pretty neat, huh?
Visualization support
You can even make graphs. To get started, install plotters Crate:
:dep plotters = { version = "0.3", default-features = false, features = ("evcxr", "all_series", "bitmap_backend", "bitmap_encoder") }
Then create a simple sine graph:
use plotters::prelude::*;
let root = SVGBackend::new("sine_wave.svg", (640, 480)).into_drawing_area();
root.fill(&WHITE).unwrap();
let mut chart = ChartBuilder::on(&root)
.caption("Sine Wave", ("Arial", 20))
.margin(5)
.x_label_area_size(30)
.y_label_area_size(30)
.build_cartesian_2d(-3.14..3.14, -1.2..1.2)
.unwrap();
chart.configure_mesh().draw().unwrap();
chart.draw_series(LineSeries::new(
(-314..314).map(|x| {
let x = x as f64 / 100.0;
(x, x.sin())
}),
&RED,
)).unwrap();
root.present().unwrap();
println!("Plot saved to sine_wave.svg");
Output:

A word on conspiracy: You can actually display inline plots directly in your notebook. But if you’re using WSL with VSCode (like I do), inline plotting may not work properly due to rendering issues on the notebook interface. So I used it as an svg file that I can easily view in my text editor.
Types of checking
Not sure what type something is? use :vars. It shows all the variables and their types:
let x = vec!(1, 2, 3);
:vars
Output:
Variable Type
x Vec
Common problems and solutions
Compilation errors everywhere
If you’re getting weird compilation errors, remember:
Slow execution
The first time you run the code in a session, it is slow due to compilation overhead. Subsequent runs are faster. If it’s really slow, you might want to:
Dependencies are not loading.
If the crate does not load:
Make sure the version exists. crates.io
Check your internet connection (it needs to download)
Try to describe the features clearly.
If things get really bad, clear the cargo cache:
rm -rf ~/.evcxr
When not to use Jupyter for rust.
Jupyter notebooks are great for learning and experimenting, but they’re not always the best choice:
Production code: Use appropriate plans with cargo.
Key performance code: The overhead is not worth it.
Major Applications: Notebooks get very dirty, very quickly
Team Collaboration: Version control with notebooks is quite the nightmare.
Stick to notebooks for prototyping and quick experiments. For anything serious, fire up your favorite editor and create a proper Rust project.
The result
Let’s summarize what you’ve learned:
How to Install EvCxR Jupyter Kernel
How to get Rust Notebook up and running
How to use external crates in a notebook
Tips and Tricks for Developing Interactive Rust
Jupyter Notebooks make Xing more accessible for learning and experimentation. Use it the next time you want to try out a quick Rust Snippet without the hassle of building a full project. And with that, we come to the end of this tutorial.
Cheers
Resources
Confessions
Thanks to Involuwapo Victor, Chinza Noqua, Holumiday Mercy, Like Ojo, Georgina Avani, And my family For the inspiration, support and knowledge used to put this post together.
And thanks to the EvCxR project maintainers for making it possible, the Rust community for being awesome, and everyone who wants to learn to read it. You inspire me everyday.