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
600
Android Memory Leak Profiling - VMFive
wdv4758h
0
200
CPython's bug in feature that nobody uses
wdv4758h
0
89
Vim 手指健康操
wdv4758h
3
760
FreeBSD ports system
wdv4758h
0
110
Featured
See All Featured
Facilitating Awesome Meetings
lara
49
6.1k
Unsuck your backbone
ammeep
668
57k
What's in a price? How to price your products and services
michaelherold
243
12k
YesSQL, Process and Tooling at Scale
rocio
167
14k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
37
1.8k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
4
320
Code Review Best Practice
trishagee
64
17k
Navigating Team Friction
lara
183
14k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
10
680
The World Runs on Bad Software
bkeepers
PRO
65
11k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
26
1.4k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
27
4.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 ?