►
From YouTube: Extending Python with Rust (Samuel Cormier-Iijima)
Description
Have you ever wanted lightning-fast code, without the segfaults and tedious boilerplate of C? Then come learn why so many Pythonistas are excited about Rust, a new language from Mozilla. After a short introduction to the language, we'll see how the Rust Python bindings let us easily write elegant, safe, and high-performance extension modules, hassle-free.
A
A
A
A
The
next
is
just
to
expand
your
tool
belt.
So
python
is
a
great
language
for
most
use
cases,
but
there's
some
cases
where
it's
not
necessarily
the
right
tool
for
the
job
and
actually
I,
just
recently
read
an
article
by
house
about
how
sentry
used
rust
to
speed
up
their
sourcemap
parsing
component.
So
that's
just
one
example
of
when
you
might
want
to
use
a
different
language,
but
most
of
all
I
just
find
it
really
fun.
A
I
think
it's
rewarding
to
learn
new
ideas
and
to
apply
new
techniques
to
solve,
towards
solving
real-world
problems
and
rust
has
a
number
of
killer
features
that
are
I'm
really
excited
about,
and
that's
why
I'm
talking
about
it
today?
The
first
is
that
it
has
a
strong
type
system.
So
it's
something
that
I've
been
noticing
in
dynamic
languages
is
that
they've
they
seem
to
be
moving
more
towards
static
typing.
A
Checkers,
like
flow
rust,
also
provides
memory
safety
and
it
provides
freedom
from
data
races,
and
these
are
both
provided
by
the
type
checker
and
finally,
it
also
provides
zero
cost
abstractions,
so
things
that
you're
used
to
in
high
level
languages
like
iterators
or
closures
or
even
pattern
matching
rust
is
able
to
have
these,
but
without
any
runtime
cost
and
it
is,
and
it
uses
LLVM
the
compiler
infrastructure
in
order
to
optimize
that
away
to
almost
nothing.
So
I
really
think
that
rust
is
a
great
language.
A
A
The
rest
compiler
has
type
inference,
meaning
that
it
can
guess
the
types
for
your
variables
based
on
how
they're
used
so
on
the
next
line,
we're
printing
hello
with
a
format
string.
This
is
very
similar
to
pythons
format,
strings,
and
this
exclamation
point
that
you
see
is
actually
what's
called
a
macro.
So
I
don't
have
too
much
time
to
talk
about
macros
today,
but
what
they
are
is,
if
you
see
the
preprocessor
for
SI
has
macros,
but
one
advantage
that
rust
has
over
a
C's
preprocessor.
A
So
here's
a
more
complex
example.
This
is
a
function
which
returns
the
average
of
a
list
of
64
bit
floating
point
values,
and
so
here
we're
putting
the
types
explicitly
on
the
function
and
the
reason
is
that
rust
isn't
able
to
infer
or
won't
infer
types
across
function,
call
boundaries
so
for
functions.
These
are
required,
and
here
we
have
a
mutable
variable.
So
a
variable
called
total
that
we're
going
to
change
as
the
function
runs.
A
We
loop
through
each
element
in
the
list:
you'll
notice,
there's
no
parentheses,
so
it's
a
bit
different
than
C,
but
it
looks
a
bit
more
like
Python
and
then
for
each
element.
We
add
it
to
the
total,
but
first
we
have
to
dereference
it
using
the
star
operator
and
the
reason
is
that
when
this
function
is
called,
it
doesn't
actually
receive
all
of
the
data
it
receives
a
pointer
or
a
reference
to
that
data.
A
And
when
you
loop
through
each
element,
you
actually
have
a
pointer
to
each
successive
element,
and
so
in
order
to
get
at
the
value
you
have
to
dereference
it
and
if
finally,
we
divide
it
by
the
length
and
there's
no
return
statement
here
in
rust.
The
last
expression
in
a
function
is
automatically
used
as
the
return
value.
A
So
this
is
what's
called
the
declarative
style.
Sorry,
the
imperative
style
of
programming.
So
that
means
that
you're
telling
the
computer
explicitly
which
steps
to
take
to
achieve
a
result,
so
higher-level
languages
normally
provide
abstractions
that
let
you
be
more
descriptive
rather
than
prescriptive,
about
how
to
achieve
a
task,
and
the
reason
that's
good
is
that
it
frees
the
interpreter
to
decide
on
how
are
the
compiler
on
how
to
actually
implement
and
how
to
do
the
execution
plan.
A
A
Ask
for
its
sum
as
a
and
then
I
type
annotated
with
a
64-bit
floating
point
and
then
divide
by
the
length
like
before,
so
this
works
and
it's
actually
the
same
speed
as
the
other
one
and
the
benefit
of
this
of
writing
it
in
this
declarative
style.
Is
that
it's
also
easier
to
parallelize
and
rust.
Actually
has
this
library
an
awesome
library
called
rayon
which
provides
optimistic
parallelism?
What
that
means
is
that
the
decision
on
whether
or
not
to
parallel
eyes
is
made
dynamically
at
runtime,
based
on
the
utilization
of
your
CPU
cores.
A
So
all
I've
changed
here
is
that
I
changed
it
err
to
parallel
adder,
and
now
this
will
run
in
parallel.
I'll
show
you
one
last
way
to
write
a
a
verge
function
and
that's
to
use
reduce.
Some
of
you
might
know
that
as
the
function
that
was
removed
in
Python
3,
but
in
rest
it's
called
fold,
and
so
it
starts
with
a
single
value
and
then
it
and
then
we
pass
it
an
operator
which
says
how
to
take
successive
values
and
combine
them
into
one.
So
this
is
an
example
of
a
closure.
A
So
you
can
see
that
the
three
sequential
versions
I'll
run
in
the
same
amount
of
time
and
the
parallel
version
ran
faster,
but
also
it
sometimes
ran
slower
and
the
variance
was
a
lot
higher.
So
that's
something
I'm,
not
completely
sure
why
it
happens
yet,
but
something
to
look
into.
So
that's
a
quick
intro
to
the
language.
So
now
I'm
just
going
to
talk
about
types
and
traits
and
rest,
so
we've
already
seen
the
primitive
types,
the
64-bit
floating-point
value.
These
are
the
other
types
that
rust
provides.
A
I'll
just
mention
that
rust
has
a
built
in
boolean
type,
which
I
think
was
a
really
good
decision,
and
it's
also
used
some
rust
forces
arguments
to
conditionals
to
be
boolean,
so
there's
no
concept
of
truthiness
or
false
eNOS,
like
in
Python
and
C,
which
doesn't
have
this
boolean
value,
there's
different
conventions
on
what
represents
success
or
failure.
Sometimes
it's
1
&
0.
A
Those
I'll
just
point
out
that
arrays
something
that
I
found
interesting
is
that
these
are
stored
on
the
stack
and
the
length
of
the
array
is
actually
a
part
of
the
type
information
which
means
for
arrays
on
the
stack
rust
can
check
at
compile
time
for
certain
bounds,
access
and
then
arrays
of
different
lengths
won't
unify,
but
the
main
way
to
create
more
complex
data
structures
and
rust
is
by
using
a
struct.
So
this
is
similar
to
how
you
would
do
it
and
see
you.
A
A
This
is
an
example
using
the
adder
library
for
python,
which,
if
you're
not
using
it,
I
highly,
recommend
and
there's
here's
how
you
would
do
the
same
type
of
thing
in
rust,
so
here's
the
same
struct,
it's
a
person
with
a
name
as
a
string
and
then
separately
from
that
you
create,
what's
called
an
inherent
implementation.
So
this
is
a
collection
of
methods
that
will
be
available
on
all
instances
of
this
person
type
and
a
bit
like
Python.
The
methods
take
an
explicit
self
parameter.
A
So
for
those
of
you
coming
from
object-oriented
languages,
you
might
be
more
familiar
with
classes
as
the
way
to
achieve
the
three
principles
of
Oh
P,
which
are
inheritance,
encapsulation
and
polymorphism,
but
rust
doesn't
really
have
classes.
What
it
has
instead
is
something
called
traits
traits
are
a
bit
like
interfaces
in
other
languages
or,
if,
like
type
classes
in
Haskell,
they're
used
for
a
number
of
things,
so
they're
used
for
operator
overloading
so
to
customize
how
addition
or
subtraction
works
or
other
operators
they're
also
used
as
indicators
of
behavior.
A
So
if
a
type
can
be
copied
or
sent
between
threads
safely,
those
that's
used
as
a
trait
that's
done
by
an
implementing
a
trait
there's,
also
used
as
bounds
on
generic
methods,
and
you
can
also
use
them
for
opt
in
dynamic
dispatch
at
runtime.
So
here's
how
you
define
a
trait
use,
the
trait
keyword,
give
it
a
name.
So
this
says
any
thing
anything
implementing
this
trait
needs
to
have
this
name
method
that
returns
a
string
and
it's
not
like
duck
typing
in
Python.
A
You
actually
implement
explicitly
need
to
implement
this
and
here's
how
you
would
use
that
trait.
You
use
the
same
employee,
word
and
you're
saying
you're
implementing
the
trait
for
that
type,
and
then
you
put
something
which
has
the
same
signature
and
you'll
notice
that
here
we're
actually
returning
self-named
clone
and
the
reason
you
need.
This
brings
me
to
the
second
thing
about
rust,
which
is
the
concepts
of
ownership
and
borrowing
so
so.
A
For
me,
this
was
the
most
difficult
part
of
rust
to
learn
and
to
understand,
but
I
also
think
it's
the
most
interesting
part
of
it
and
it's
really
I
think
a
major
breakthrough
in
language
design
and
the
the
running
joke
is
that
you'll
be
fighting
with
the
borrowed
checker
for
your
first
couple
of
weeks
of
using
rust
but
I
think
it's
worth
it
once
you
get
past
that
and
also
this
is
what
really
provides
the
guarantees
of
safety
and
of
data
race.
Freedom
in
rust,
so
I
think
it's
easier
to
understand.
A
A
So
as
soon
as
V
goes
out
of
scope
and
as
soon
as
this
function
returns
that
data
on
the
heap
is
freed,
so
this
isn't
like
C,
where
you
need
to
manually
call
free
for
data
that
you've
allocated
and
if
I
assign
this
to
another
variable
like
W,
that
ownership
has
been
transferred
to
W
and
if
I
then
try
to
use
V
afterwards,
we
get
an
error,
and
that's
because
that
ownership
has
been
moved
and
we
can't
use
that
value.
That
variable
anymore.
A
Look
at
another
example,
so
here's
a
function
called
print.
It
takes
a
vector
and
prints
it,
and
so
here,
if
we,
if
we
call
print
this,
call
transfers
ownership
into
the
function
and
when
print
returns,
that
data
is
freed,
which
means
that
if
we
try
to
call
print
again
with
that
same
variable,
we'll
get
an
error.
A
A
So
borrowing
follows
a
number
of
rules
that
are
what
guarantee
the
properties
of
memory
safety.
The
first
is
that
mutable
borrows
are
exclusive.
Once
you
have
a
single
mutable
borrow
to
a
object,
you
can't
have
any
other
active
borrows
at
the
same
time,
and
the
second
is
that
a
borrow
can't
outlive
the
object
that
is
being
borrowed.
So
just
to
show
you
two
examples
of
that.
Here's,
the
first
one
that
if
you
have
a
number
of
borrows
to
object
as
soon
as
you
try
to
take
a
mutable
one,
because
those
are
still
active.
A
This
is
forbidden
and
rust
will
give
you
a
compile
time,
error
and
here's
another
example
with
what's
called
lifetimes.
So
if
you
have
this
outer
variable
and
then
inside
the
scope,
you
have
a
variable
V
and
you
try
to
assign
it
a
reference
to
of
to
that
variable
to
the
outer.
As
soon
as
this
goes
out
of
scope,
V
is
going
to
be
freed,
and
so
this
gives
you
an
error
saying
that
V
doesn't
live
long
enough.
A
So
I've
kind
of
I
think
it's
probably
too
much
to
cover.
In
one
talk
all
of
this,
you
could
actually
probably
do
a
whole
talk
just
on
this
subject.
It's
based
off
something
called
a
concept
in
logic
called
sub
structural
logic,
and
for
those
of
you
who
are
familiar
with
the
curry,
Howard
isomorphism,
which
is
this
correspondence
between
types
in
type
theory
and
proofs
and
propositions
in
logic.
This
is
a
type
system
known
as
a
fine
types
and
it's
actually
an
active
area
of
research
to
prove
that
this
system
is
consistent
and
safe.
A
A
The
benefit
of
that
is
that
it
will
work
with
any
interpreter,
but
the
problem
is
that
your
rust
code
won't
have
access
to
the
interpreter
objects
and
the
second
way
of
doing
that,
which
is
what
I'll
talk
about
today,
is
by
using
the
C
Python
bindings,
and
so
the
benefit
of
this
is
that
you
can
actually
access
a
lot
of
the
interpreter.
Internals,
however,
you're
limited
to
the
C
Python
interpreter
and
to
make
this
more
exciting
I'm
going
to
do
this
as
a
live
demo,
and
hopefully
the
demo
gods
are
with
me
today.
A
You
see
my
screen
so
I
have
a
function
here
in
Python
called
count
doubles
and
what
this
does
is
it
takes
a
string
and
it
looks
for
the
number
of
pairs
of
characters
that
are
identical,
so
two
A's
in
a
row
or
two
B's
in
a
row
and
so
on
so
I
have
a
variable
called
total
and
I
loop
through
the
string
with
zipped
with
the
string
offset
by
one.
So
this
gives
me
pairs
of
characters
in
the
string
and,
if
they're,
equal,
I,
increment
the
total
and
then
I
return
it.
A
So
this
is
a
bit
slow
in
Python,
there's
a
way
to
speed
it
up,
which
is
by
using
a
reg
X,
which
does
the
exact
same
thing.
But
maybe
you
want
to
make
this
even
faster
and
to
do
that,
you
can
actually
write
a
pipe
extension
module.
So
let
me
show
you
how
to
do
that.
So
the
first
thing
I'm
going
to
do
is
I'm
going
to
create
a
new
crate
or
which
is
what
Russ
calls
packages.
A
A
So
first,
if
I
wanted
to
just
pull
in
the
latest,
released
version,
I
could
say
this
of
the
C
Python
bindings,
but
to
get
the
latest
and
greatest
I'm
going
to
pull
this
in
from
github,
and
the
other
thing
we
want
to
say
is
that
we're
building
a
shared
library
so
I'm
going
to
give
this
library
a
name.
This
is
what
we
import
it
as
from
Python
and
then
I'm
gonna
say
that
I'm
building
a
crate
whose
type
is
a
dynamically
linked,
shared
library.
A
So
that's
all
we
need
for
this
file
and
then
rust
or
cargo
has
also
created.
This
file
called
Lib,
and
this
is
where
we
put
our
code.
So
the
first
thing
we're
going
to
do
is
pull
in
the
C
Python
crate
and
we
want
to
use
all
of
the
macros
that
that
create,
defines
and
now
I'm
going
to
pull
in
a
couple
of
types
from
that
crate.
The
first
is
Python
and
the
second
is
PI
result
and
I'll
explain
these
in
a
second
and
now
I'm
going
to
build
the
function,
so
this
is
count
doubles.
A
This
is
what's
going
to
count
the
number
of
pairs
of
characters
in
my
string.
The
first
argument
is
going
to
be
this
Python
object.
The
second
one
is
the
string,
and
this
returns
a
PI
result.
So
this
pi
result
is
the
object
that
lets
us
raise
python
exceptions.
If
we
want
to-
and
it's
generic
over
this
unsigned
64-bit
number
so
then
we're
going
to
write
just
the
function,
but
what
I
want
you
to
notice
is
how
similar
this
is
to
the
Python
version.
A
So
I
have
the
total
and
then
I
loop
through
the
pairs
of
characters
in
the
characters
of
the
string
and
then
I
zip
this
with
the
characters
offset
by
one.
So
this
is
very
similar
to
the
zip
call
and
Python,
and
now,
if
those
two
characters
are
equal
I'm
going
to
increment
the
total
and
I'm
going
to
return
well,
I
don't
need
to
return
I'm
going
to
say
that
there
was
everything
was
okay
and
return
the
total.
So
this
is
all
we
need.
A
This
is
just
ten
lines
of
code
and
we're
gonna
make
this
important
bill
from
Python,
sir,
and
this
is
a
macro
that
the
cpython
binding
is
defined.
We
pass
it
the
name
of
our
module
and
then
the
name
of
the
function
for
python,
2,
&,
3
and
then
the
last
argument
here
is
a
closure
which
receives
a
module
object
and
lets
us,
modify
it
and
add
different
methods
to
it.
So
what
I'm
going
to
do
is
I'm
going
to
add
function
to
this
module
call.
A
It
count,
doubles
you're
supposed
to
tell
me
if
I
make
it
type
and
we
use
this
PI
FN
macro,
which
builds
the
Python
version
of
the
function.
So
here's
count
doubles
and
then
we
also
give
it
the
type
that
we
want
it
to
be.
The
arguments
and
that's
all
we
need
for
this
and
just
say:
ok,
so
that's
that's
all
we
need
now.
A
So
this
is
a
reference
to
the
Python
interpreter
and
there's
something
in
Python
called
the
global
interpreter
lock,
and
any
access
to
interpreter
internals
needs
to
be
holding
this
lock
and
the
way
that
rust
achieves
this,
so
that
the
rust
bindings
achieves
this
is
by
having
using
the
lifetime
concept
and
saying
that,
as
long
as
you
have
reference
or
as
long
as
you
have
this
object
alive,
you
have
the
glue
the
interpreter
lock.
So
this
is
a
really
nice
way
of
getting
around
having
to
do
this
manually
and
see.
A
Ok,
so
this
is
done
so
you'll
notice
that
what's
been
built
in
here
is
this
example
shared
library.
So
what
I
can
do
is
I
can
copy
it,
I'll
copy
it,
to
example,
dot
Esso,
and
this
means
that
it
can
be
found
by
python
and
now,
if
I
import
example,
it's
just
a
simple
Python
module
that
has
this
count,
doubles
function
and
I
can
pass
it.
A
string
and
it'll
tell
me
how
many
pairs
of
characters
it
found
inside
that
string.
A
There,
okay,
so
yeah.
So
this
tells
me
how
many
times
there
were
a
pairs
of
characters
in
the
string
and
just
to
show
you
that
the
bindings
will
also
do
automatic
marshaling
of
the
types.
So,
if
I
try
to
pass
this
something,
that's
not
a
string,
I
get
a
type
error
and
just
to
show
you
the
comparison
in
terms
of
performance,
we
can
compare
all
of
those
different
versions
of
the
count
doubles
function.
A
So
this
is
benchmarking
all
three
versions,
and
we
can
see
that
the
rust
one
took
about
here's
the
mean
took
about
two
milliseconds.
On
average,
the
reg
X
took
about
30
milliseconds,
so
12
x
floor
and
then
the
pure
Python
one
took
about
16
milliseconds,
so
about
30
x,
floor
and
I
ran
this
test
in
pi
PI
just
to
check,
and
it's
still
about
five
to
eight
times
slower
than
the
rest,
one.
So
just
to
wrap
up.
A
A
Okay,
yeah,
so
just
to
wrap
up
I.
Think
rust
is
a
really
good
way
to
speed
up
critical
parts
of
your
code.
I
encourage
you
to
take
a
look
at
it.
I
hope,
I've,
piqued,
your
interest
and
one
of
the
rust
communities.
Big
focuses
in
2017
is
the
story
of
the
integration
with
other
languages
like
Python,
so
expect
to
see
a
lot
of
improvements
in
how
cargo
and
setup
tools
work
together,
and
these
are
just
some
references
that
I
would
recommend
taking
a
look
at
and
that's
it.
B
C
A
I
can
explain
so
there's
the
arrow
type
and
rust
the
rust
doesn't
have
the
exceptions
like
python.
Does
it
has
this
error
type?
This
question
mark
is
new
syntax
in
rust,
1.14
I
believe
for
1.13.
That
was
just
released
and
what
that
does.
Is
it
basically
checks
for
an
error
and
if
there's
an
error,
it
raises
it
up
and
returns
it
as
a
and
courses
it
into
an
error
of
the
appropriate
type.
So
it's
a
bit
like
try
catch,
but
it's
used
so
often
that
they
added
specific
syntax
for
it.
D
Hey
so
Russ
has
a
bunch
of
like
specific
stuff,
like
borrowing
in
order
ship
that
Python
doesn't
have
so
like
I
see
in
your
function.
Count
doubles
you're,
taking
you're
taking
you're,
not
taking
ownership,
you're
borrowing
it.
So
what
happens?
If
you
don't
borrow,
and
you
take
ownership
so
like
from
Python,
you
have
to
think
about
that
stuff.
Like
oh
well,
I'm
calling
a
function,
I
can
only
call
a
function.
That's
taking
a
borrow
of
my
variable,
not
ownership,
or
something
like
that.
You
have
to
think
about
that
kind
of
stuff.
A
A
So
yes,
if
you
take
a
borrow,
then
it'll
increment
the
reference
count
and
then
or
I
don't
think
it
needs
to
incrementing
at
all,
but
if
you're
not
taking
a
borrow
I
think
the
bindings
will
actually
check
that
for
you
and
make
sure
that,
as
those
are
not
handled
appropriately,
so
use
something
to
be
aware
of,
but
what's
nice
is
that
the
compiler
will
check
on
these
lifetimes,
and
so
you
end
up
having
the
same
type
of
safety
properties.
There's
still
some
things
to
be
figured
out.
A
E
E
A
This
is
a
method,
that's
called
the
same
thing
in
rust,
but
this
is
a
method.
That's
a
part
of
native
rust,
iterator,
so
you'll
notice
here
what
I'm,
taking
isn't
a
PI
isn't
a
Python
object.
I
could
do
that.
If
I
did
this
and
then
I
would
have
access
to
all
of
the
methods
on
the
Python
methods
on
this
object.
But
what
I'm
taking
is
actually
this
reference
to
a
string
and
what
that
means
is
that
the
bindings
will
marshal
this
into
a
native
rust
string
and
it
doesn't
do
a
copy.
A
F
A
I've
been
doing
a
little
bit
of
work
on
this.
You
they'll
need
obviously
the
rust
compiler
if
they're
going
to
compile
it
from
source.
There's
a
setup
tools
package
called
rust
ext,
which
tries
to
make
that
as
seamless
as
possible.
So
you
can
just
have
a
setup
that
PI
file
and
say
that
there's
a
rust
file
that
gets
compiled
I
think
that
can
still
use
some
improvement.
C
A
So
we
work
I
work
at
Survey
Monkey
and
we
mostly
do
web
or
I've
work
on
the
enterprise
team
and
we
build
web
applications
and
for
the
most
part,
I
think
Python
is
actually
really
good
and
good
enough.
Actually
for
for
that,
so
there
haven't
been
any
cases
where
we
need
to
have
something:
that's
a
lot
faster.
This
has
been
more
of
the
kind
of
hobby
and
just
a
passion,
that's
something
that
I've
been
excited
about,
and
maybe
we
can
use
it
if
something
comes
up
where
you
need
something.
That's
faster.