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
150
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
660
Android Memory Leak Profiling - VMFive
wdv4758h
0
250
CPython's bug in feature that nobody uses
wdv4758h
0
96
Vim 手指健康操
wdv4758h
3
840
FreeBSD ports system
wdv4758h
0
130
Featured
See All Featured
Agile that works and the tools we love
rasmusluckow
329
21k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
32
2.3k
Git: the NoSQL Database
bkeepers
PRO
430
65k
Optimizing for Happiness
mojombo
379
70k
Raft: Consensus for Rubyists
vanstee
139
7k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
137
34k
Large-scale JavaScript Application Architecture
addyosmani
512
110k
Adopting Sorbet at Scale
ufuk
77
9.4k
What's in a price? How to price your products and services
michaelherold
245
12k
Building Adaptive Systems
keathley
43
2.6k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
30
2.1k
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 ?