Skip to content

Commit

Permalink
readme: slightly improve getting started notes
Browse files Browse the repository at this point in the history
  • Loading branch information
davidhewitt committed Jul 30, 2021
1 parent 3241467 commit 9948d51
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 16 deletions.
54 changes: 39 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,20 @@ PyO3 supports Python 3.6 and up. The minimum required Rust version is 1.41.

PyPy is also supported. Some minor features are unavailable on PyPy - please refer to the [pypy section in the guide](https://pyo3.rs/latest/building_and_distribution/pypy.html) for more information.

You can either write a native Python module in Rust, or use Python from a Rust binary.
You can use PyO3 to write a native Python module in Rust, or to embed Python in a Rust binary. The following sections explain each of these in turn.

However, on some OSs, you need some additional packages. E.g. if you are on _Ubuntu 18.04_, please run
### Using Rust from Python

```bash
sudo apt install python3-dev python-dev
```
PyO3 can be used to generate a native Python module. The easiest way to try this out for the first time is to use [`maturin`](https://github.com/PyO3/maturin). `maturin` is a tool for building and publishing Rust-based Python packages with minimal configuration. The following steps set up some files for an example Python module, install `maturin`, and then show how build and import the Python module.

## Using Rust from Python

PyO3 can be used to generate a native Python module.
First, create a new folder (let's call it `string_sum`) containing the following two files:

**`Cargo.toml`**

```toml
[package]
name = "string-sum"
authors = "PyO3 Contributors"
version = "0.1.0"
edition = "2018"

Expand Down Expand Up @@ -65,23 +62,50 @@ fn sum_as_string(a: usize, b: usize) -> PyResult<String> {
Ok((a + b).to_string())
}

/// A Python module implemented in Rust.
/// A Python module implemented in Rust. The name of this function should match
/// the `lib.name` setting in the `Cargo.toml`, else Python will not be able to
/// import the module.
#[pymodule]
fn string_sum(py: Python, m: &PyModule) -> PyResult<()> {
fn string_sum(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(sum_as_string, m)?)?;

Ok(())
}
```

While developing, you can symlink (or copy) and rename the shared library from the target folder: On MacOS, rename `libstring_sum.dylib` to `string_sum.so`, on Windows `libstring_sum.dll` to `string_sum.pyd`, and on Linux `libstring_sum.so` to `string_sum.so`. Then open a Python shell in the same folder and you'll be able to `import string_sum`.
With those two files in place, now `maturin` needs to be installed. This can be done using Python's package manager `pip`. First, load up a new Python `virtualenv`, and install `maturin` into it:

```bash
$ cd string_sum
$ python -m venv .env
$ source .env/bin/activate
$ pip install maturin
```

To build, test and publish your crate as a Python module, you can use [maturin](https://github.com/PyO3/maturin) or [setuptools-rust](https://github.com/PyO3/setuptools-rust). You can find an example for setuptools-rust in [examples/word-count](https://github.com/PyO3/pyo3/tree/main/examples/word-count), while maturin should work on your crate without any configuration.
Now build and execute the module:

## Using Python from Rust
```bash
$ maturin develop
# lots of progress output as maturin runs the compilation...
$ python
>>> import string_sum
>>> string_sum.sum_as_string(5, 20)
'25'
```

As well as with `maturin`, it is possible to build using [`setuptools-rust`](https://github.com/PyO3/setuptools-rust) or [manually](https://pyo3.rs/latest/building_and_distribution.html#manual-builds). Both offer more flexibility than `maturin` but require further configuration.

### Using Python from Rust

To embed Python into a Rust binary, you need to ensure that your Python installation contains a shared library. The following steps demonstrate how to ensure this (for Ubuntu), and then give some example code which runs an embedded Python interpreter.

To install the Python shared library, if you are on _Ubuntu 18.04_, you can run:

```bash
sudo apt install python3-dev
```

If you want your Rust application to create a Python interpreter internally and
use it to run Python code, add `pyo3` to your `Cargo.toml` like this:
Start a new project with `cargo new`. Next, add `pyo3` to your `Cargo.toml` like this:

```toml
[dependencies.pyo3]
Expand Down
2 changes: 1 addition & 1 deletion guide/src/building_and_distribution.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ You can also symlink (or copy) and rename the shared library from the `target` f
- on Windows, rename `libyour_module.dll` to `your_module.pyd`.
- on Linux, rename `libyour_module.so` to `your_module.so`.

You can then open a Python shell in the same folder and you'll be able to use `import your_module`.
You can then open a Python shell in the same folder and you'll be able to run `import your_module`.

## `Py_LIMITED_API`/`abi3`

Expand Down

0 comments on commit 9948d51

Please sign in to comment.