#file #file-path #pyo3 #file-like-object

pyo3-file

A small helper library for working with python file-like objects with rust

16 releases (10 breaking)

new 0.12.0 Apr 1, 2025
0.11.0 Mar 17, 2025
0.10.0 Nov 23, 2024
0.8.1 Jun 11, 2024
0.2.0 May 20, 2019

#46 in FFI

Download history 1160/week @ 2024-12-17 283/week @ 2024-12-24 597/week @ 2024-12-31 980/week @ 2025-01-07 1363/week @ 2025-01-14 1536/week @ 2025-01-21 1527/week @ 2025-01-28 1123/week @ 2025-02-04 706/week @ 2025-02-11 913/week @ 2025-02-18 1117/week @ 2025-02-25 1229/week @ 2025-03-04 1127/week @ 2025-03-11 1290/week @ 2025-03-18 1109/week @ 2025-03-25 1585/week @ 2025-04-01

5,610 downloads per month

MIT/Apache

14KB
233 lines

crates.io

PyO3-File

This is a small utility library to facilitate working with python file-like objects with rust.

Example

An example use case for this is when a file is opened in python, and needs to be passed to a rust library.

We could support both by introspecting the PyObject, and pick the correct behavior.

We would like this to work:

from path_or_file_like import accepts_path_or_file_like

def main():
    # should open `some_file.txt`.
    accepts_path_or_file_like("./some_file.txt")

    # should read from the python handle.
    f = open('./some_file.txt')
    accepts_path_or_file_like(f)

We could use pyo3_file to extend an existing a pyo3 module.

use pyo3_file::PyFileLikeObject;
use pyo3::types::PyString;

use pyo3::prelude::*;
use pyo3::wrap_pyfunction;
use std::io::Read;
use std::fs::File;

/// Represents either a path `File` or a file-like object `FileLike`
#[derive(Debug)]
enum FileOrFileLike {
    File(String),
    FileLike(PyFileLikeObject),
}

impl<'py> FromPyObject<'py> for FileOrFileLike {
    fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
        // is a path
        if let Ok(string) = ob.extract::<String>() {
            return Ok(FileOrFileLike::File(string));
        }

        // is a file-like
        let f = PyFileLikeObject::py_with_requirements(ob.clone(), true, false, true, false)?;
        Ok(FileOrFileLike::FileLike(f))
    }
}

#[pyfunction]
/// Opens a file or file-like, and reads it to string.
fn accepts_path_or_file_like(path_or_file_like: FileOrFileLike) -> PyResult<String> {
    match path_or_file_like {
        FileOrFileLike::File(s) => {
            println!("It's a file! - path {}", s);
            let mut f = File::open(s)?;
            let mut string = String::new();

            f.read_to_string(&mut string)?;
            Ok(string)
        }
        FileOrFileLike::FileLike(mut f) => {
            println!("Its a file-like object");
            let mut string = String::new();

            f.read_to_string(&mut string)?;
            Ok(string)
        }
    }
}

#[pymodule]
fn path_or_file_like(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_wrapped(wrap_pyfunction!(accepts_path_or_file_like))?;

    Ok(())
}


# fn main() {}

Dependencies

~2.2–4MB
~70K SLoC