Pyo3: How can I import Python code into Rust?

Created on 2 May 2018  路  3Comments  路  Source: PyO3/pyo3

The documentation doesn't seem to be clear on that.

Context: what I'd like to do is to import this code into my Rust Drops of Diamond project for blob serialization with building sharding with Ethereum. It would be nice if I could copy and paste a Python file into a Rust file, and make a few modifications to make it compatible with Rust. At the moment the documentation doesn't seem to be clear on how to do that. It seems to talk about using Rust to make a Python compatible library, but not using Python in Rust.

question

Most helpful comment

Hi @jamesray1,

I think this is feasible (although not documented at all) by doing the following:

To embed the Python file within Rust:

  • use include_str! to embed your Python source into your compiled executable / library
  • use pyo3::Python.eval to add all your function definitions to the locals

To use an external Python file:

  • make sure it is in the path (possibly, edit it through py.import("sys")?.get("path"))
    (you can also simply edit sys.path within Rust to import the required Python library, but from that will work only if you have installed the Python script to a particular location)
  • use eval to define your function within the interpreter

Then you can have access to your function and call it with an argument that implements Into<PyList> for instance.

With an external file, the code looks like so:

extern crate pyo3;

use pyo3::prelude::*;

fn main() {
   let gil = Python::acquire_gil();
   let py = gil.python();

   let syspath: &PyList = py.import("sys")
     .unwrap()
     .get("path")
     .unwrap()
     .try_into()
     .unwrap();

   syspath.insert(0, "path/to/your/module").unwrap();

   let evm_utils = py.import("evm.utils").unwrap();
   evm_utils.call1("serialize_blobs", ...);

}

All 3 comments

Hi @jamesray1,

I think this is feasible (although not documented at all) by doing the following:

To embed the Python file within Rust:

  • use include_str! to embed your Python source into your compiled executable / library
  • use pyo3::Python.eval to add all your function definitions to the locals

To use an external Python file:

  • make sure it is in the path (possibly, edit it through py.import("sys")?.get("path"))
    (you can also simply edit sys.path within Rust to import the required Python library, but from that will work only if you have installed the Python script to a particular location)
  • use eval to define your function within the interpreter

Then you can have access to your function and call it with an argument that implements Into<PyList> for instance.

With an external file, the code looks like so:

extern crate pyo3;

use pyo3::prelude::*;

fn main() {
   let gil = Python::acquire_gil();
   let py = gil.python();

   let syspath: &PyList = py.import("sys")
     .unwrap()
     .get("path")
     .unwrap()
     .try_into()
     .unwrap();

   syspath.insert(0, "path/to/your/module").unwrap();

   let evm_utils = py.import("evm.utils").unwrap();
   evm_utils.call1("serialize_blobs", ...);

}

I have tried to make importing work with different packages inside the Rust code with the example above. But I wasn't successful. Can you point me out how do you import external python code?

import numpy as np

def test(args):
    return args

Code above throws PyErr:

Err(PyErr { type: Py(0x100a28cd0, PhantomData) })

602

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rth picture rth  路  5Comments

fcangialosi picture fcangialosi  路  6Comments

vorner picture vorner  路  7Comments

davidhewitt picture davidhewitt  路  5Comments

thedrow picture thedrow  路  5Comments