Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Python module in Rust
Search
dv
June 08, 2017
0
140
Python module in Rust
dv
June 08, 2017
Tweet
Share
More Decks by dv
See All by dv
First try for CAS, SymPy with codegen
wdv4758h
0
640
Android Memory Leak Profiling - VMFive
wdv4758h
0
220
CPython's bug in feature that nobody uses
wdv4758h
0
95
Vim 手指健康操
wdv4758h
3
810
FreeBSD ports system
wdv4758h
0
120
Featured
See All Featured
Measuring & Analyzing Core Web Vitals
bluesmoon
6
320
Building a Scalable Design System with Sketch
lauravandoore
462
33k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
60k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
134
33k
We Have a Design System, Now What?
morganepeng
51
7.5k
Building Adaptive Systems
keathley
40
2.5k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
44
7.1k
Into the Great Unknown - MozCon
thekraken
35
1.7k
Music & Morning Musume
bryan
46
6.4k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
50
2.4k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
3.8k
Building a Modern Day E-commerce SEO Strategy
aleyda
38
7.2k
Transcript
Python module in Rust Chiu-Hsiang Hsu PyCon TW 2017
Who am I • Software Engineer @ Deep Sentinel (My
First Job !) • Last Year: First try for CAS, SymPy with codegen • GitHub: @wdv4758h
Talk's Assumption Version: Python 3.6 Platform: Linux Your Skills: Some
Python, Some C
Fast overview of Rust ecosystem
Rust Survey 2016 Python
Rust Language: Why Rust Memory Safety without GC Compiled Language
Strong, Static Type
Who is using Rust ? https://www.rust-lang.org/friends.html
Benchmarks Game http://benchmarksgame.alioth.debian.org/
Benchmarks Game - Where is Python different weight class ...
Benchmarks Game - Python http://benchmarksgame.alioth.debian.org/
Rust is young May 15, 2015
Rust 1.18.0 (2017-06-08) 6 week release cycle
Crates (like PyPI) https://crates.io/
Cargo (like pip + setuptools) http://doc.crates.io/
rustup (like pyenv) https://www.rustup.rs/
rustup (like pyenv) compiler version
rustup (like pyenv) target platform
RFCs (like PEP) https://github.com/rust-lang/rfcs
Official Tutorial https://doc.rust-lang.org/book/
Standard Library Documentation https://doc.rust-lang.org/std/
Documentation for Crates You can build your docs by cargo
doc API doc with your docstring autogen for your crates: https://docs.rs/
Documentation for Crates https://docs.rs/
Documentation for Crates https://docs.rs/
Official Repos https://github.com/rust-lang/
Official Repos https://github.com/rust-lang-nursery/
Rust is a lower level language than Python
Lower Level https://doc.rust-lang.org/std/fmt/index.html format! (like str.format)
Lower Level . Rust iterator (like Python iterator) https://doc.rust-lang.org/std/iter/trait.Iterator.html
Lower Level . Rust iterator (like Python iterator) https://doc.rust-lang.org/std/iter/trait.Iterator.html
Lower Level . Rust iterator (like Python iterator) https://doc.rust-lang.org/std/iter/trait.Iterator.html
Lower Level . Rust iterator (like Python iterator) https://doc.rust-lang.org/std/iter/trait.Iterator.html
Lower Level .. Rust lambda (like Python lambda) https://doc.rust-lang.org/book/closures.html
Lower Level ... Wait ! It doesn't look like that
low level !?
Lower Level ... Wait ! It doesn't look like that
low level !? I pick what I want to show you :P
Compiler
Compiler
Compiler
Compiler
Python Code • Pure Python Code • Python Code +
Binary built from (C/C++/…) • Python Code + Other Language's Code
Python + Binary Make Friends !
How can Python play with binary • ctypes • CFFI
• CPython Extension • ...
ctypes • pip • IPython • PyInstaller • SymPy •
prompt_toolkit • ... Cases CPython Extension • NumPy • Pillow • simplejson • TensorFlow • psutil • ... CFFI • Cryptography • psycopg2cffi • pyzmq • ...
ctypes - quick view import ctypes from ctypes import c_char_p
, c_void_p lib = ctypes.cdll.LoadLibrary("pycontw.so") lib.hello_world.argtypes = (c_void_p,) lib.hello.argtypes = (c_char_p,) lib.hello.restypes = c_char_p
ctypes - flow C Code Shared Library Python Code ctypes
libffi
CFFI - quick view from cffi import FFI ffi =
FFI() lib = ffi.dlopen("pycontw.so") ffi.cdef(""" void hello_world(); char* hello(const char* name); """)
CFFI - flow (ABI level) C Code Shared Library Python
Code CFFI libffi
CPython Extension - import PyInit_pycontw() import pycontw Find Pure Python
Package or Module Find pycontw.so
CPython Extension - flow C Code Shared Library Python Code
CPython C API
CPython Extension - simple call path import Find <modulename>.so POSIX
dlsym PyModule_Create() PyInit_<modulename>()
CPython Extension - quick view static PyMethodDef pycontw_methods[] = {
{"hello_world", hello_world, METH_VARARGS, NULL}, {"hello", hello, METH_VARARGS, NULL}, {NULL, NULL, 0, NULL} };
CPython Extension - quick view static PyModuleDef pycontw_module = {
PyModuleDef_HEAD_INIT, "pycontw", "PyCon TW 2017", -1, pycontw_methods, NULL, NULL, NULL, NULL };
CPython Extension - quick view PyMODINIT_FUNC PyInit_pycontw() { return PyModule_Create(&pycontw_module);
}
CPython Extension - quick view And you need to implement
functions with CPython C API
CPython Extension - build from distutils.core import setup, Extension module1
= Extension('pycontw', sources = ['cpython-extension-sample.c']) setup(name = 'pycontw', version = '1.0', description = 'This is a demo package', ext_modules = [module1])
CPython Extension - build $ python setup.py build
Back to things related to Python
Rust with ctypes/CFFI ?
Sure
CPython + Rust: by ctypes or CFFI #[repr(C)] struct MyData
{ a: i32, // Other members... }
CPython + Rust: by ctypes or CFFI extern "C" fn
myfunc() { println!("It's PyCon TW 2017 !!!"); }
CPython + Rust: by ctypes or CFFI • ctypes: use
it like C • CFFI: provide a C header for Rust code
Rust for CPython Extension ?
not so easy, but possible
CPython + Rust: by rust-cpython Repo: github.com/wdv4758h/pycontw-rust-module
CPython Extension with rust-cpython Rust Code Shared Library Python Code
rust-cpython CPython C API
rust-cpython - quick view // things like Python "import" #[macro_use]
extern crate cpython; use cpython::{PyObject, PyResult, Python};
rust-cpython - quick view fn hello_world(py: Python) -> PyResult<PyObject> {
println!("It's PyCon TW 2017"); Ok(py.None()) }
rust-cpython - quick view fn hello(_: Python, name: &str) ->
PyResult<String> { Ok(format!("It's PyCon TW 2017, hello {} !!!", name)) }
rust-cpython - quick view py_module_initializer!(pycontw, initpycontw, PyInit_pycontw, |py, m| {
m.add(py, "__doc__", "PyCon TW 2017")?; m.add(py, "hello", py_fn!(py, hello(name: &str)))?; m.add(py, "hello_world", py_fn!(py, hello_world()))?; Ok(()) });
rust-cpython - Cargo.toml [package] name = "pycontw" version = "0.1.0"
[lib] name = "pycontw" crate-type = ["cdylib"] [dependencies] cpython = { version = "0.1.0", features = ["extension-module"] }
rust-cpython - build $ cargo build
rust-cpython - build $ cargo build --release
setuptools-rust https://github.com/PyO3/setuptools-rust
setuptools-rust - setup.py from setuptools import setup from setuptools_rust import
RustExtension setup( name='pycontw', version='2017', rust_extensions=[RustExtension('pycontw', './Cargo.toml')], packages=['pycontw'], # Rust extensions are not zip safe, just like C extensions zip_safe=False, )
Build Your Rust CPython Extension $ python setup.py build
CPython Extension in Rust Simple Examples
Hello
Print
Hash
Hash with random sate
Rust Vec for Python
Dropbox Brotli in Rust
Dropbox Brotli in Rust Simple Wrapper
Dropbox Brotli in Rust - Cargo.toml [dependencies] brotli = "1.0.8"
Dropbox Brotli in Rust - src/lib.rs extern crate brotli as
_brotli; use _brotli::enc::reader::CompressorReader; py_module_initializer!(pycontw, initpycontw, PyInit_pycontw, |py, m| { m.add(py, "brotli", py_fn!(py, brotli(data: Vec<u8>)))?; Ok(()) });
Dropbox Brotli in Rust - src/lib.rs fn brotli(_: Python, data:
Vec<u8>) -> PyResult<Vec<u8>> { let quality = 5_u32; let lg_window_size = 20_u32; let mut enc_data = vec![]; let mut reader = CompressorReader::new(data.as_slice(), 4096, quality, lg_window_size); let _ = reader.read_to_end(&mut enc_data); Ok(enc_data) }
More Resource- Rust by Example http://rustbyexample.com/
More Resource - Awesome Rust https://github.com/rust-unofficial/awesome-rust
Future Work • Build module by CI for multiple platforms
• Cross Compile module • More complete Python & Rust integration • ...
Question ?