py2rs
From Python into Rust
let x = Rust::from("Python");
A quick reference guide for the Pythonista in process of becoming a Rustacean.
Monty Python - Season 3 - Episode 49
Mrs. Jalin: George.
Mr. Jalin: Yes, Gladys.
Mrs. Jalin: There's a man at the door with a moustache.
Mr. Jalin: Tell him I've already got one. (Mrs. Jalin hits him hard with a newspaper)
All right, all right. What's he want then?
Mrs. Jalin: He says do we want a documentary on crustaceans.
Mr. Jalin: Crustaceans!
Mrs. Jalin: Yes.
Mr. Jalin: What's he mean, crustaceans?
Mrs. Jalin: CRUSTACEANS!! GASTROPODS! LAMELLIBRANCHS! CEPHALOPODS!
...
Ok... watch it later... let's learn some Rust now...
Getting Started with Rust
Assuming you already know what is Rust and already decided to start learning it. Here are some steps for you to follow:
- Take a tour of Rust Syntax and Coding Style and Tour if Rust
- Watch some screencasts to get basics of Ownership &Borrowing concept
http://intorust.com/ or if you understand Portuguese watch Aprenda Rust - Follow this set of runnable examples to understand how everything fit together
https://doc.rust-lang.org/stable/rust-by-example/ - Now it is time to read your first book, you can pick:
-
Rust Essentials
A good introduction to Rust language in a more
superficial
approach which results in a very pleasant and easy reading, recommended even for those who are not experienced with low level systems languages.- Paparback and e-book available on Packt Publisher
https://www.packtpub.com/application-development/rust-essentials-second-edition
- Paparback and e-book available on Packt Publisher
-
TRPL (The Rust Programming language Book)
- Official Book
- Free to read online
- Available as paperback or e-book (buy at Amazon)
-
- Read some real examples
- Rust Cookbook This Rust Cookbook is a collection of simple examples that demonstrate good practices to accomplish common programming tasks, using the crates of the Rust ecosystem.
- Anthology
- Patterns and Good Practices
Exercises
Time to put your new knowledge in action solving some exercises.
-
Exercism.io
Register a new account on exercism.io (using github auth)
Install exercism command line client on your computer
Solve some exercises: https://www.exercism.io/languages/rust/ -
Rust Playground
Run Live Rust Code in the browser with https://play.rust-lang.org/ -
Rustlings Small exercises to get you used to reading and writing Rust code. Clone the repo and follow the guide. This is a great way to get used to dialogue with the compiler. Interactive rust exercises: https://github.com/rust-lang/rustlings
Getting updated
Now I assume you are addicted to Rust and you want to be updated about everything around it, here are some good links to follow.
-
This Week in Rust Newsletter
https://this-week-in-rust.org/ -
Awesome Rust Newsletter
https://rust.libhunt.com/ -
Reddit
http://reddit.com/r/rust (serious sub-reddit)
http://reddit.com/r/rustjerk (almost memes only) -
Official Twitter
https://twitter.com/rustlang
Interact with other Rustaceans
Don't be afraid, the Rustaceans are a very receptive species and are cozy with the Pythonistas.
Main Community links
https://www.rust-lang.org/en-US/community.html
Local Communities
-
Brazil
- General
- Rust BH
- Rust in POA
-
Indonesia
-
Russia
-
Add your country/city here, send a Pull Request.
Additional learning resources
- Learning Rust
- Rust Learning
- Rust Guidelines (WIP)
- Rust Design Patterns and Idioms
- Idiomatic Rust
- GTK Rust Tutorial
- Effective use of iterators
- Red Hat Developers: Speed up Your Python with Rust
- What's a reference in Rust? (The best article to understand
'lifetimes
and&
)
Facts
- The language is named Rust because "rust is as close to the bare metal as you can get".,
in metal theory rust is the chemical layer closest to bare metal.
(also Wikipedia says that the name was possibly inspired by the name of a Fungi) - The Rust
trifecta
is 1) Memory Safe, 2) Fast 3) Concurrent - Rust can be used for web development
- Rust can be used for Gaming Development
- Rust can be used for Machine Learning
- Lots of IDEs and Editors supports Rust (VSCode is known to have the better support by now)
- Rust packages are called
Crates
and are installed byCargo
explore them at http://crates.io - In Rust there is no Class but Structs, Enums, Traits, functions and macros!
- Rust compiler was first written in OCaml then rewritten in Rust! (Rust is written in Rust!!!)
- Rust type system is strongly inspired by Haskell
- Rust functional style is inspired by Erlang
- Rust type inference is mainly inspired by ML and also by Haskell
- The main syntax style is inspired by C and C++
- There is no automated Garbage Collector so Rust frees memory based on Resource Aquisition RAII (a.k.a Ownership)
- Rust has Generic Types!!!
- As Rust is close to bare metal you can ship a program without the inclusion of Rust's runtime which makes easy to distribute programs (no need of dependencies and virtuelenvs management)
- Graydon Hoare (creator of Rust) is now working at Apple developing the Swift language
- Rust is the developers most loved language according to Stack Overflow Survey
- Rust is the most energy efficient language! and that is very important for environment, data center companies and maybe it can help saving your laptop and phone battery in near future.
- There is an Operating System written in Rust - Redox
- Mozilla released the fastest version of Firefox (quantum) having many parts written on Rust
- The Rust mascot (unofficial) is called Ferris and it is a crab (There is no record of the official reason about being a crab, the reasonable history is that it was inspired by the Rusty Crab a common species of crab and also a name of a famous restaurant.)
- To compliment your fellow Rustaceans don't say
cheers!. Say safe! (safe! is also said when toasting with champagne at Rust conferences) - Rust is to become a second programming language for the Linux kernel (see here)
- Rust is the language choosen by Microsoft to rewrite parts of Windows Kernel
More facts? and curiosities send a question here or send a Pull Request adding an interest fact to this list.
Glossary of terms
Term | Definition |
---|---|
crate | A rust distributable package |
ferris | The unofficial Crab Mascot |
Rustacean | The Rust programmer or evangelist or enthusiastic |
nightly | The unstable toolchain of the Rust compiler |
impl | Implementation |
General
Python | Definition | Rust |
---|---|---|
PEP8 | Guidelines and conventions | RustAPI Guidelines |
PEPS | Enhancement Proposals / RFC | Rust RFCs |
PSF | Organization / Foundation | [Rust Foundation](https://foundation.rust-lang.org/ |
PyCon | Main Conference | RustConf |
Guido Van Rossum | Creator | Graydon Hoare |
1989 | First appeared | 2010 |
1991 | First Release | 2012 |
PSF | License | Apache 2.0 and MIT |
C | Implemented in | Rust |
.py, .pyw, .pyc | File Extensions | .rs, .rlib |
http://github.com/python/cpython | Repository | https://github.com/rust-lang/rust |
Pyladies, AfroPython | Diversity and Inclusion initiative | RustBridge |
comp.lang.Python | Official Users Forum | users.rust-lang.org |
Environment Tools
Python | Definition | Rust |
---|---|---|
requirements.txt | Official dependency tracker file | Cargo.toml |
setup.py | Official installator / distributor file | Cargo.toml |
PyPI | Library repository | Crates.io |
pip | Library installation | Cargo |
setuptools and poetry | Library distribution | Cargo |
pbr | Library distribution | Cargo |
pipenv and poetry | Dependency manager | Cargo |
twine | Package uploader | Cargo and Semantic |
venv * | Isolated environments | Cargo |
pyinstaller | Generate standalone executables | Cargo |
pyenv | Install and manage versions of language | rustup |
pydoc and sphinx | Generate documentation from code | rustdoc and Cargo |
python | Interpreter / Compiler | rustc and Cargo |
ipython | REPL | iRust |
ipdb | Debugger | rust-gdb |
Extending Python with C or C++ | Foreign language interface | PyO3 |
Libraries and Frameworks
Python | Definition | Rust |
---|---|---|
urllib * | HTTP calls | hyper |
requests | Simplified HTTP calls | reqwest |
json | JSON parsing loading and dumping | serde |
pyYAML | YAML parsing loading and dumping | serde |
lxml | XML parsing loading and dumping | RustyXML |
csv * | CSV parsing | rust-csv |
datetime * & Dateutils | Date & time | Chrono |
click and argparse | CLI Framework | clap |
docopt | CLI Framework | docopt |
re * | Regular Expressions | regex |
subprocess * | Run external commands | subprocess |
multiprocessing * | Multiprocessing | Rayon |
logging * | Logging | log |
Pathlib * | Path manipulation | fs and fs_extra |
cryptography | Crytography | crypto |
pickle * | Object serialization | RON |
heapq * | Heap queue | BinaryHeap * |
bottle | Minimal web framework | Iron |
flask | Web framework | Rocket |
django | Full stack web framework | DO NOT EXIST YET |
SQL Alchemy | Relational database ORM | Diesel |
Pymongo | MongoDB driver | mongodb |
Jinja 2 | Template engine | Tera |
pygtk | GTk desktop development | gtk |
pyside | QT desktop development | rust-qt |
pygame | 2D UI library / gaming | ggez & Conrod & Piston |
unitest2 | Test framework | Builtin |
nose | Test runner | Cargo |
pytest | Testing framework and runner | Polish |
Flake8 | Linter | Clippy |
autopep8 and black | Auto formatter | rustfmt |
twisted | Network application framework | libpnet |
AsyncIO * | Async application framework | Tokio and futures |
Pillow | Image manipulation | Image |
Beautiful Soup | HTML parser | html5ever |
Hypothesis | Data driven test framework | Quickcheck and proptest |
mock | Test mocking | Mockers |
bioPython | Bioinformathics libraries | Rust Bio |
Dynaconf | Config management | Config |
itertools * | Data structure iteration | Rust Itertools |
Geopython | Geo spatial data | Geo Rust |
ScikitLearn | Machine learning | rusty-machine |
mistune | Markdown / Common Mark Parser | cmark |
celery | Distributed computation | Antimony |
boto | AWS clients | rusoto |
AstroPy | Astronomy | astro-rust |
Numpy | Numeric | Numeric |
Pandas | Dataframes | Polars |
Applications
Python | Definition | Rust |
---|---|---|
Pelican | Static Site generator | Cobalt |
ansible | Infra Orchestration | realize |
mkdocs | Generate documentation and e-books from Markdown | mdBook |
locust | HTTP load test | drill |
Nameko | Microservices Framework | fractalide |
Quokka CMS | CMS | Nickel CMS |
Useful crates
Add Pythonic features to Rust
Python | Definition | Rust |
---|---|---|
{'foo': "bar"} | Syntax to create a dict / hashmap | maplit |
__init__(self, value='default') | Instance initialization (with some default values) | derive_new |
itertools *stdlib | Extra iterators methods | itertools |
hashlib * | Password Hashing | libpasta |
Show me The code
From Python to Rust by examples
You can copy-paste and run the Rust examples in https://play.rust-lang.org/ and Python in https://repl.it/languages/python3
- Creating a new project
- Installing new libraries/crates
- Hello World
- Types and Declarations
- Define a function
- List/Slice
- Dict/Map
- Set/HashSet
- While and For loops
- Files
- Exceptions/Return Error
- Concurrency
- Communicating between threads
- Sorting
- Web app with Flask / Rocket
- HTTP Request with error handling
- Multithreaded HTTP Crawler
- Encode and Decode JSON
- Object Orientation
- Print Object for Debug/Log
- Operator Overloading
- Template for new examples
Creating a new project
Create a new project with basic files, entry points, module initializer, dependency and installation artifacts.
Python
$ mkdir {pyproject,pyproject/src}
$ touch {pyproject/src/{__init__.py,__main__.py,program.py},pyproject/{requirements.txt,setup.py}}
$ echo "-e ." >> pyproject/requirements.txt
$ echo "from setuptools import setup" >> pyproject/setup.py
$ echo "setup(author=..., name=...)" >> pyproject/setup.py
Rust
#![allow(unused)] fn main() { $ cargo new my-rust-program }
Installing new libraries/crates
Python
$ pip install foo
Rust
$ cargo install foo
running--compiling
Python
$ python my_python_program.py
Rust
$ cargo run
In Rust, there is a --release
flag that allows for more compile time optimization to be done, but it will take longer to compile
$ cargo run --release
Hello World
Python
if __name__ == "__main__":
print("Hello, World")
Rust
fn main() { println!("Hello, World"); }
Types and Declarations
Create new objects, values on basic primitive types and also data structures.
Python
age = 80
name = 'daffy'
weight = 62.3
loons = ['bugs', 'daffy', 'taz']
ages = { # Ages for 2017
'daffy': 80,
'bugs': 79,
'taz': 63,
}
Rust
use std::collections::HashMap; fn main() { let age = 80; let name = "daffy"; let weight = 62.3; let mut loons = vec!["bugs", "daffy", "taz"]; let mut ages = HashMap::new(); // Ages for 2017 ages.insert("daffy", 80); ages.insert("bugs", 79); ages.insert("taz", 63); }
Define a function
Defining a function that takes 2 integer arguments and returns its sum.
Python
def add(a, b):
"""Adds a to b"""
return a + b
Python with typing annotations
It looks more similar to Rust.
def add(a: int, b: int) -> int:
"""Adds a to b"""
return a + b
Rust
#![allow(unused)] fn main() { /// Adds a to b fn add(a: i32, b: i32) -> i32 { a + b } }
List/Slice
Creating a list, adding new elements, gettings its length, slicing by index, iterating using for loop and iterating with enumerator.
Python
names = ['bugs', 'taz', 'tweety']
print(names[0]) # bugs
names.append('elmer')
print(len(names)) # 4
print(names[2:]) # ['tweety', 'elmer']
for name in names:
print(name)
for i, name in enumerate(names):
print('{} at {}'.format(name, i))
Rust
fn main() { let mut names = vec!["bugs", "taz", "tweety"]; println!("{}", names[0]); // bugs names.push("elmer"); println!("{}", names.len()); // 4 println!("{:?}", &names[2..]); // ["tweety", "elmer"] for name in &names { println!("{}", name); } for (i, name) in names.iter().enumerate() { println!("{} at {}", i, name); } }
.step_by() is the equivalent for python's range/xrange step parameter.
python:
for i in range(0,10,2):
print(i) # 0, 2, 4, 6, 8
rust:
#![allow(unused)] fn main() { for i in (0..10).step_by(2) { println!("{}", i); // 0, 2, 4, 6, 8 } }
Dict/Map
Create new dictionaries (hash maps), adding new keys and values, changing values, getting by key, checking if a key is containing, etc.
Python
# Creating a new dict and populating it
ages = {}
ages['daffy'] = 80
ages['bugs'] = 79
ages['taz'] = 63
# or doing the same using a for loop
ages = {}
for name, age in [("daffy", 80), ("bugs", 79), ("taz", 63)]:
ages[name] = age
# or initializing from a list
ages = dict([("daffy", 80), ("bugs", 79), ("taz", 63)])
# or passing key values on creation
ages = { # Ages for 2017
'daffy': 80,
'bugs': 79,
'taz': 63,
}
ages['elmer'] = 80
print(ages['bugs']) # 79
print('bugs' in ages) # True
del ages['taz']
for name in ages: # Keys
print(name)
for name, age in ages.items(): # Keys & values
print('{} is {} years old'.format(name, age))
Rust
use std::iter::FromIterator; use std::collections::HashMap; fn main() { // Creating a new HashMap and populating it let mut ages = HashMap::new(); // Ages for 2017 ages.insert("daffy", 80); ages.insert("bugs", 79); ages.insert("taz", 63); // or doing the same using a loop let mut ages = HashMap::new(); for &(name, age) in [("daffy", 80), ("bugs", 79), ("taz", 63)].iter() { // For non-Copy data, remove & and use iter().clone() ages.insert(name, age); } // or initializing from Array let mut ages: HashMap<&str, i32> = // Ages for 2017 [("daffy", 80), ("bugs", 79), ("taz", 63)] .iter().cloned().collect(); // or initializing from Vec (Iterator) let mut ages: HashMap<&str, i32> = // Ages for 2017 HashMap::from_iter( vec![ ("daffy", 80), ("bugs", 79), ("taz", 63) ] ); ages.insert("elmer", 80); println!("{}", ages["bugs"]); // 79 println!("{}", ages.contains_key("bugs")); // true ages.remove("taz"); for name in ages.keys() { // Keys println!("{}", name); } for (name, age) in &ages { // Keys & values println!("{} is {} years old", name, age); } }
Pythonic alternative to dict/map in Rust
You can use the maplit crate to load hashmap!
macro to have an efficient sugared (a.k.a Pythonic) syntax!
# Cargo.toml
[dependencies]
maplit = "*"
then
#![allow(unused)] fn main() { #[macro_use] extern crate maplit; let map = hashmap!{ "daffy" => 80, "bugs" => 79, "taz" => 63, }; }
set / HashSet
Create a set
(a hash of unique keys), add new keys and compute intersection
, difference
and union
Python
# creating and populating
colors = set()
colors.add("red")
colors.add("green")
colors.add("blue")
colors.add("blue")
# using literal syntax
colors = {'red', 'green', 'blue', 'blue'}
# from an iterator
colors = set(['red', 'green', 'blue', 'blue'])
# deduplication
print(colors) # {"blue", "green", "red"}
# operations
colors = {'red', 'green', 'blue', 'blue'}
flag_colors = {"red", "black"}
# difference
colors.difference(flag_colors) # {'blue', 'green'}
# symmetric difference
colors.symmetric_difference(flag_colors) # {'black', 'blue', 'green'}
# intersection
colors.intersection(flag_colors) # {'red'}
# union
colors.union(flag_colors) # {'black', 'blue', 'green', 'red'}
Rust
use std::collections::HashSet; use std::iter::FromIterator; fn main() { // creating and populating - type inference let mut colors = HashSet::new(); colors.insert("red"); colors.insert("green"); colors.insert("blue"); colors.insert("blue"); // from an iterator - explicit type let mut colors: HashSet<&str> = HashSet::from_iter(vec!["red", "green", "blue", "blue"]); // deduplication println!("{:?}", colors); // {"blue", "green", "red"} // Operations let mut colors: HashSet<&str> = HashSet::from_iter(vec!["red", "green", "blue", "blue"]); let mut flag_colors: HashSet<&str> = HashSet::from_iter(vec!["red", "black"]); // difference colors.difference(&flag_colors); // ["green", "blue"] // symmetric difference colors.symmetric_difference(&flag_colors); // ["blue", "green", "black"] // intersection colors.intersection(&flag_colors); // ["red"] // union colors.union(&flag_colors); // ["red", "blue", "green", "black"] }
or syntax sugared using maplit crate
#![allow(unused)] fn main() { #[macro_use] extern crate maplit; let colors = hashset!{"red", "green", "blue", "blue"}; }
while and for loops
Looping until a condition is met or over an iterable object.
Python
# While loop
counter = 0
while counter < 10:
print(counter)
counter += 1
# infinite while loop
while True:
print("loop Forever!")
# infinite while loop with break
counter = 0
while True:
print(counter)
counter += 1
if counter >= 10:
break
# while loop with continue
counter = 0
while True:
counter += 1
if counter == 5:
continue
print(counter)
if counter >= 10:
break
# For loop over a list
for color in ["red", "green", "blue"]:
print(color)
# Enumerating indexes
for i, color in enumerate(["red", "green", "blue"]):
print(f"{color} at index {i}")
# For in a range
for number in range(0, 100):
print(number) # from 0 to 99
Rust
fn main() { // While loop let mut counter = 0; while counter < 10 { println!("{}", counter); counter += 1; } // infinite while loop loop { println!("Loop forever!"); } // infinite while loop with break let mut counter = 0; loop { println!("{}", counter); counter += 1; if counter >= 10 { break; } } // infinite while loop with continue let mut counter = 0; loop { counter += 1; if counter == 5 { continue; } println!("{}", counter); if counter >= 10 { break; } } // for loop over a list for color in ["red", "green", "blue"].iter() { println!("{}", color); } // Enumerating indexes for (i, color) in ["red", "green", "blue"].iter().enumerate() { println!("{} at index {}", color, i); } // for in a range for number in 0..100 { println!("{}", number); // from 0 to 99 } }
Loop Labels
Rust has a looping feature which is not present on Python: Loop labels
#![allow(unused)] fn main() { 'outer: for x in 0..10 { 'inner: for y in 0..10 { if x % 2 == 0 { continue 'outer; } // continues the loop over x if y % 2 == 0 { continue 'inner; } // continues the loop over y println!("x: {}, y: {}", x, y); } } }
Files
Read a text file and iterate its lines printing the content, properly close the file at the end.
Python
from pathlib import Path
with Path("/tmp/song.txt").open() as fp:
# Iterate over lines
for line in fp:
print(line.strip())
Rust
use std::io::{BufReader, BufRead}; use std::fs::File; use std::path::Path; fn main () { let fp = File::open(Path::new("/tmp/song.txt")).unwrap(); let file = BufReader::new(&fp); for line in file.lines() { // Iterate over lines println!("{}", line.unwrap()); } }
Exceptions/Return Error
Expecting for exceptions and identifying errors.
Python
def div(a, b):
if b == 0:
raise ValueError("b can't be 0")
return a / b
# ...
try:
div(1, 0)
except ValueError:
print('An error occurred!')
Rust
fn div(a: i32, b: i32) -> Result<i32, &'static str> { if b == 0 { Err("b can't be 0") } else { Ok(a / b) } } fn main() { match div(1, 0) { Ok(_) => {}, Err(_) => println!("An error occurred!"), }; }
Concurrency
Python
thr = Thread(target=add, args=(1, 2), daemon=True)
thr.start()
Rust
#![allow(unused)] fn main() { use std::thread; thread::spawn(|| { add(5,5); }); }
Communicating between threads
Managing data context between threads.
Python
from queue import Queue
queue = Queue()
# ...
# Send message from a thread
queue.put(353)
# ...
# Get message to a thread
val = queue.get()
Rust
use std::thread; use std::sync::mpsc; fn main() { let (tx, rx) = mpsc::channel(); let sender = thread::spawn(move || { let val = String::from("hi"); tx.send(val.clone()).unwrap(); println!("Sent {}", val); }); let receiver = thread::spawn(move || { let received = rx.recv().unwrap(); println!("Received: {}", received); }); sender.join(); receiver.join(); }
Sorting
Sorting lists, reversing and using a key.
Python
names = ['taz', 'bugs', 'daffy']
# Lexicographical order
names.sort()
# Reversed lexicographical order
names.sort(reverse=True)
# Sort by length
names.sort(key=len)
Rust
fn main() { let mut names = ["taz", "bugs", "daffy"]; // Lexicographical order names.sort(); // Reversed lexicographical order names.sort_by(|a, b| b.cmp(a)); // Sort by length names.sort_by_key(|a| a.len()); }
Web app with Flask / Rocket
Python
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Hello Python'
if __name__ == '__main__':
app.run(port=8080)
Rust
#![feature(plugin)] #![plugin(rocket_codegen)] extern crate rocket; #[get("/")] fn index() -> &'static str { "Hello Rust" } fn main() { rocket::ignite().mount("/", routes![index]).launch(); }
HTTP Request with error handling
Python
Using requests
import requests
url = 'https://httpbin.org/ip'
try:
resp = requests.get(url)
except HTTPError as err:
msg = f"error: cannot get {url} - {err}"
raise SystemExit(msg)
assert resp.status_code == 200
print(f"The response content is: {resp.content}")
Rust
using reqwest
extern crate reqwest; use std::io::Read; fn main() { let url = "https://httpbin.org/ip"; let mut resp = match reqwest::get(url) { Ok(response) => response, Err(e) => panic!("error: could not perform get request {}", e), }; assert!(resp.status().is_success()); let mut content = String::new(); resp.read_to_string(&mut content).expect("valid UTF-8"); println!("The response content is: {}", content); }
Multithreaded HTTP Crawler
Python
Using requests
from concurrent.futures import ThreadPoolExecutor
import requests
URLS = (
"https://httpbin.org/html",
"https://httpbin.org/links/10/0",
"https://httpbin.org/robots.txt",
"https://httpbin.org/user-agent",
"https://httpbin.org/links/10/0",
"https://httpbin.org/robots.txt",
"https://httpbin.org/xml",
"https://httpbin.org/redirect/1",
"https://httpbin.org/redirect/2",
"https://httpbin.org/cookies",
"https://httpbin.org/basic-auth/user/passwd",
"https://httpbin.org/gzip",
)
def crawl_worker(url):
try:
print(f"Response of url: {url} is {requests.get(url).status_code}")
except Exception:
print("Failed to get url.")
if __name__ == "__main__":
with ThreadPoolExecutor() as executor:
executor.map(crawl_worker, URLS)
Rust
using reqwest
extern crate reqwest; use std::thread; fn crawl_worker(url: &str) { let parsed_url = reqwest::Url::parse(url).expect("Bad url format."); let response = reqwest::get(parsed_url).expect("Failed to get url."); println!("Response of url: {} is {:?}", url, response.status().to_string()); } fn main() { let urls = vec![ "https://httpbin.org/html", "https://httpbin.org/links/10/0", "https://httpbin.org/robots.txt", "https://httpbin.org/user-agent", "https://httpbin.org/links/10/0", "https://httpbin.org/robots.txt", "https://httpbin.org/xml", "https://httpbin.org/redirect/1", "https://httpbin.org/redirect/2", "https://httpbin.org/cookies", "https://httpbin.org/basic-auth/user/passwd", "https://httpbin.org/gzip", ]; let mut queue = vec![]; for url in urls { queue.push(thread::spawn(move || { crawl_worker(url); })); } for job in queue { let _ = job.join(); } }
Encode and Decode JSON
Python
import json
# Decode/Deserialize
data = '''{
"name": "bugs",
"age": 76
}'''
person = json.loads(data)
# Do things like with any other Python data structure
print(f"{person['name']} was born {person['age']} years ago")
# Encode/Serialize
serialized = json.dumps(obj)
print(f"The serialized value is: {serialized}")
Rust
extern crate serde; extern crate serde_json; #[macro_use] extern crate serde_derive; #[derive(Serialize, Deserialize)] struct Person { name: String, age: u8, } fn main() { // Decode/Deserialize let data = r#"{"name": "bugs", "age": 76}"#; let p: Person = match serde_json::from_str(data) { Ok(person) => person, Err(e) => panic!("error: could not deserialize: {}", e), }; // Do things just like with any other Rust data structure. println!("{} was born {} years ago.", p.name, p.age); // Encode/Serialize let serialized = serde_json::to_string(&p).unwrap(); println!("The serialized value is: {}", serialized); }
Object Orientation
Python
class Cat:
def __init__(self, name):
self.name = name
def greet(self, other):
print("Meow {}, I'm {}".format(other, self.name))
# ...
grumy = Cat('Grumpy')
grumy.greet('Garfield') # Meow Garfield, I'm Grumpy
Rust
struct Cat { name: String } impl Cat { pub fn new<S>(name: S) -> Cat where S: Into<String> { Cat { name: name.into() } } pub fn greet<S: Into<String>>(&self, other:S) { println!("Meow {}, I'm {}", other.into(), self.name); } } fn main() { let grumpy = Cat::new("Grumpy"); grumpy.greet("Garfield"); // Meow Garfield, I'm Grumpy }
NOTE: In Rust, it is best to avoid
stringly types APIs
so in the above example it would be better if we dolet garfield = Cat::new("Garfield")
and then makegreet
to accept an instance ofCat
asother
argument. If you are interested watch this.
Print Object for Debug/Log
Print formatted object debug information
Python
class Actor:
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return str(self.__dict__)
daffy = Actor(
name='Daffy',
age=80,
)
print('{!r}'.format(daffy)) # {'name': 'Daffy', 'age': 80}
Rust
#[derive(Debug)] struct Actor { name: String, age: i32 } fn main() { let daffy = Actor {name: "Daffy".into(), age: 80}; println!("{:#?}", daffy); // Actor {name: "Daffy", age: 80 } }
Operator overloading
Python and Rust allows the overload of the behavior of operators such as +, -, /, *, %
In both examples the operator +
(add) is being overloaded to implement the Rock, Paper, Scissors game.
Python implementation uses its Protocol Oriented Programming, by looking for the __add__
method, which is part of the structural Summable protocol.
Rust does the same, but using trait implementation, in this case we implement ops::Add<T> for T
Both are, despite the syntax differences, very similar on the concept.
Python
from enum import Enum
from typing import Self
class Object(Enum):
Rock = 1
Paper = 2
Scissors = 3
def __add__(self, other: Self) -> Self:
match self:
case Object.Rock if other is Object.Scissors:
return self
case Object.Scissors if other is Object.Paper:
return self
case Object.Paper if other is Object.Rock:
return self
case _:
return other
if __name__ == "__main__":
assert Object.Rock + Object.Scissors is Object.Rock
assert Object.Scissors + Object.Paper is Object.Scissors
assert Object.Paper + Object.Rock is Object.Paper
assert Object.Rock + Object.Rock is Object.Rock
assert Object.Paper + Object.Paper is Object.Paper
assert Object.Scissors + Object.Scissors is Object.Scissors
Rust
use std::ops; #[derive(Debug, PartialEq)] enum Object { Rock, Paper, Scissors, } impl ops::Add<Object> for Object { type Output = Object; fn add(self, other: Object) -> Object { match self { Object::Rock if other == Object::Scissors => self, Object::Scissors if other == Object::Paper => self, Object::Paper if other == Object::Rock => self, _ => other, } } } fn main() { assert_eq!(Object::Rock + Object::Scissors, Object::Rock); assert_eq!(Object::Scissors + Object::Paper, Object::Scissors); assert_eq!(Object::Paper + Object::Rock, Object::Paper); assert_eq!(Object::Rock + Object::Rock, Object::Rock); assert_eq!(Object::Scissors + Object::Scissors, Object::Scissors); assert_eq!(Object::Paper + Object::Paper, Object::Paper); }
Template for new examples
Explanation comes here.
Python
# python code goes here
Rust
#![allow(unused)] fn main() { // rust code goes here }
Credits
Created by Bruno Rocha @rochacbruno inspired by https://www.353.solutions/py2go/index.html
First published in BrunoRocha.org
Mdbook deploy and formatting by Rapha-Borges
Send a Pull Request or Suggestion as a new issue.
Contributors
Thanks goes to these wonderful people (emoji key):
This project follows the all-contributors specification. Contributions of any kind welcome!