Embedding Python in Rust to Call External Python Libraries

I’m trying to learn how to embed Python into a Rust application. For learning purposes, I want to create a Rust script/app that runs a forever loop. This loop sleeps for a set interval, and upon waking, it uses the Python requests library to fetch the current time from an internet time server. While this isn’t a practical application, my goal is to understand how to call external Python libraries from Rust.

My ultimate goal is to see if I can integrate a Python BACnet stack into a Rust application.

My Setup

  • main.rs
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>use pyo3::prelude::*;
use pyo3::types::IntoPyDict;
use std::thread;
use std::time::Duration;
fn main() -> PyResult<()> {
// Safely acquire the GIL and run the Python code
Python::with_gil(|py| {
// Print the version of Python being used
py.run("import sys; print('Python version:', sys.version)", None, None)?;
// Import the requests library in Python
let requests = py.import("requests")?;
loop {
// Sleep for 10 seconds
thread::sleep(Duration::from_secs(10));
// Execute the Python code to get the current time from a time server
let locals = [("requests", requests)].into_py_dict(py);
let time_response: String = py.eval(
r#"
import requests
response = requests.get('http://worldtimeapi.org/api/timezone/Etc/UTC')
response.json()['datetime']
"#,
None,
Some(locals)
)?.extract()?;
// Print the time received from the server
println!("Current UTC Time: {}", time_response);
}
Ok(())
})
}
</code>
<code>use pyo3::prelude::*; use pyo3::types::IntoPyDict; use std::thread; use std::time::Duration; fn main() -> PyResult<()> { // Safely acquire the GIL and run the Python code Python::with_gil(|py| { // Print the version of Python being used py.run("import sys; print('Python version:', sys.version)", None, None)?; // Import the requests library in Python let requests = py.import("requests")?; loop { // Sleep for 10 seconds thread::sleep(Duration::from_secs(10)); // Execute the Python code to get the current time from a time server let locals = [("requests", requests)].into_py_dict(py); let time_response: String = py.eval( r#" import requests response = requests.get('http://worldtimeapi.org/api/timezone/Etc/UTC') response.json()['datetime'] "#, None, Some(locals) )?.extract()?; // Print the time received from the server println!("Current UTC Time: {}", time_response); } Ok(()) }) } </code>
use pyo3::prelude::*;
use pyo3::types::IntoPyDict;
use std::thread;
use std::time::Duration;

fn main() -> PyResult<()> {
    // Safely acquire the GIL and run the Python code
    Python::with_gil(|py| {
        // Print the version of Python being used
        py.run("import sys; print('Python version:', sys.version)", None, None)?;

        // Import the requests library in Python
        let requests = py.import("requests")?;

        loop {
            // Sleep for 10 seconds
            thread::sleep(Duration::from_secs(10));

            // Execute the Python code to get the current time from a time server
            let locals = [("requests", requests)].into_py_dict(py);
            let time_response: String = py.eval(
                r#"
                import requests
                response = requests.get('http://worldtimeapi.org/api/timezone/Etc/UTC')
                response.json()['datetime']
                "#,
                None,
                Some(locals)
            )?.extract()?;

            // Print the time received from the server
            println!("Current UTC Time: {}", time_response);
        }

        Ok(())
    })
}
  • Cargo.toml
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>[package]
name = "rust_python_time_fetcher"
version = "0.1.0"
edition = "2021"
[dependencies]
pyo3 = { version = "0.21.2", features = ["extension-module"] }
[build-dependencies]
pyo3-build-config = "0.21.2"
</code>
<code>[package] name = "rust_python_time_fetcher" version = "0.1.0" edition = "2021" [dependencies] pyo3 = { version = "0.21.2", features = ["extension-module"] } [build-dependencies] pyo3-build-config = "0.21.2" </code>
[package]
name = "rust_python_time_fetcher"
version = "0.1.0"
edition = "2021"

[dependencies]
pyo3 = { version = "0.21.2", features = ["extension-module"] }

[build-dependencies]
pyo3-build-config = "0.21.2"
  • build_with_python.sh
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>#!/bin/bash
# Activate the virtual environment
source env/bin/activate
# Get the path to the Python interpreter
PYTHON=$(which python3)
# Get the Python version
PYTHON_VERSION=$($PYTHON -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')")
# Set the path to the Python interpreter
export PYO3_PYTHON="$PYTHON"
# Set the paths for Python libraries and include files
export LD_LIBRARY_PATH="$($PYTHON -c "import sysconfig; print(sysconfig.get_config_var('LIBDIR'))"):$LD_LIBRARY_PATH"
export LIBRARY_PATH="$($PYTHON -c "import sysconfig; print(sysconfig.get_config_var('LIBDIR'))"):$LIBRARY_PATH"
export PYTHONPATH="$($PYTHON -c "import site; print(site.getsitepackages()[0])"):$PYTHONPATH"
# Include and lib directories might vary based on how Python was installed or the distro specifics
export CFLAGS="$($PYTHON -c "import sysconfig; print('-I' + sysconfig.get_paths()['include'])")"
export LDFLAGS="$($PYTHON -c "import sysconfig; print('-L' + sysconfig.get_config_var('LIBDIR'))")"
# Now try running Cargo build again
cargo build
# Print Python version and path
$PYTHON --version
which $PYTHON
# Print Python includes and libs
$PYTHON-config --includes
$PYTHON-config --libs
</code>
<code>#!/bin/bash # Activate the virtual environment source env/bin/activate # Get the path to the Python interpreter PYTHON=$(which python3) # Get the Python version PYTHON_VERSION=$($PYTHON -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')") # Set the path to the Python interpreter export PYO3_PYTHON="$PYTHON" # Set the paths for Python libraries and include files export LD_LIBRARY_PATH="$($PYTHON -c "import sysconfig; print(sysconfig.get_config_var('LIBDIR'))"):$LD_LIBRARY_PATH" export LIBRARY_PATH="$($PYTHON -c "import sysconfig; print(sysconfig.get_config_var('LIBDIR'))"):$LIBRARY_PATH" export PYTHONPATH="$($PYTHON -c "import site; print(site.getsitepackages()[0])"):$PYTHONPATH" # Include and lib directories might vary based on how Python was installed or the distro specifics export CFLAGS="$($PYTHON -c "import sysconfig; print('-I' + sysconfig.get_paths()['include'])")" export LDFLAGS="$($PYTHON -c "import sysconfig; print('-L' + sysconfig.get_config_var('LIBDIR'))")" # Now try running Cargo build again cargo build # Print Python version and path $PYTHON --version which $PYTHON # Print Python includes and libs $PYTHON-config --includes $PYTHON-config --libs </code>
#!/bin/bash

# Activate the virtual environment
source env/bin/activate

# Get the path to the Python interpreter
PYTHON=$(which python3)

# Get the Python version
PYTHON_VERSION=$($PYTHON -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')")

# Set the path to the Python interpreter
export PYO3_PYTHON="$PYTHON"

# Set the paths for Python libraries and include files
export LD_LIBRARY_PATH="$($PYTHON -c "import sysconfig; print(sysconfig.get_config_var('LIBDIR'))"):$LD_LIBRARY_PATH"
export LIBRARY_PATH="$($PYTHON -c "import sysconfig; print(sysconfig.get_config_var('LIBDIR'))"):$LIBRARY_PATH"
export PYTHONPATH="$($PYTHON -c "import site; print(site.getsitepackages()[0])"):$PYTHONPATH"

# Include and lib directories might vary based on how Python was installed or the distro specifics
export CFLAGS="$($PYTHON -c "import sysconfig; print('-I' + sysconfig.get_paths()['include'])")"
export LDFLAGS="$($PYTHON -c "import sysconfig; print('-L' + sysconfig.get_config_var('LIBDIR'))")"

# Now try running Cargo build again
cargo build

# Print Python version and path
$PYTHON --version
which $PYTHON

# Print Python includes and libs
$PYTHON-config --includes
$PYTHON-config --libs

The Problem
When I try to build the project with cargo build, I encounter the following error:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>> cargo build
Compiling pyo3-build-config v0.21.2
error: failed to run custom build command for `pyo3-build-config v0.21.2`
Caused by:
process didn't exit successfully: `C:UsersbbartlingDesktoprust_python_timetargetdebugbuildpyo3-build-config-6b34c9835096c15dbuild-script-build` (exit code: 1)
--- stdout
cargo:rerun-if-env-changed=PYO3_CONFIG_FILE
cargo:rerun-if-env-changed=PYO3_NO_PYTHON
cargo:rerun-if-env-changed=PYO3_ENVIRONMENT_SIGNATURE
cargo:rerun-if-env-changed=PYO3_PYTHON
cargo:rerun-if-env-changed=VIRTUAL_ENV
cargo:rerun-if-env-changed=CONDA_PREFIX
cargo:rerun-if-env-changed=PATH
--- stderr
error: no Python 3.x interpreter found
</code>
<code>> cargo build Compiling pyo3-build-config v0.21.2 error: failed to run custom build command for `pyo3-build-config v0.21.2` Caused by: process didn't exit successfully: `C:UsersbbartlingDesktoprust_python_timetargetdebugbuildpyo3-build-config-6b34c9835096c15dbuild-script-build` (exit code: 1) --- stdout cargo:rerun-if-env-changed=PYO3_CONFIG_FILE cargo:rerun-if-env-changed=PYO3_NO_PYTHON cargo:rerun-if-env-changed=PYO3_ENVIRONMENT_SIGNATURE cargo:rerun-if-env-changed=PYO3_PYTHON cargo:rerun-if-env-changed=VIRTUAL_ENV cargo:rerun-if-env-changed=CONDA_PREFIX cargo:rerun-if-env-changed=PATH --- stderr error: no Python 3.x interpreter found </code>
> cargo build
   Compiling pyo3-build-config v0.21.2
error: failed to run custom build command for `pyo3-build-config v0.21.2`                                                     

Caused by:
  process didn't exit successfully: `C:UsersbbartlingDesktoprust_python_timetargetdebugbuildpyo3-build-config-6b34c9835096c15dbuild-script-build` (exit code: 1)
  --- stdout
  cargo:rerun-if-env-changed=PYO3_CONFIG_FILE
  cargo:rerun-if-env-changed=PYO3_NO_PYTHON
  cargo:rerun-if-env-changed=PYO3_ENVIRONMENT_SIGNATURE
  cargo:rerun-if-env-changed=PYO3_PYTHON
  cargo:rerun-if-env-changed=VIRTUAL_ENV
  cargo:rerun-if-env-changed=CONDA_PREFIX
  cargo:rerun-if-env-changed=PATH

  --- stderr
  error: no Python 3.x interpreter found

What I’ve Tried
I created a build_with_python.sh script ran on a rasp pi to set up the environment correctly, including activating a virtual environment and setting the necessary paths for Python libraries and include files. However, I’m still facing the same error.

Questions

  • How can I correctly configure my Rust project to recognize and use
    the Python interpreter and libraries from my virtual environment?
  • Are there any additional steps I need to take to ensure that the pyo3
    crate can find and use the Python interpreter?
  • Any tips or guidance would be greatly appreciated!

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật