Использовать многопроцессорную библиотеку python в Rust - PullRequest
3 голосов
/ 25 февраля 2020

Я использую Rust для ускорения конвейера обработки данных, но мне нужно запустить существующий код Python как есть, который я хочу распараллелить. После обсуждения в другом вопросе создание нескольких Python процессов является возможным подходом, учитывая определенные c ограничения моего проекта. Однако выполнение приведенного ниже кода дает бесконечное значение l oop. Я не совсем понимаю, почему.

use cpython::Python;

fn main() {
    let gil = Python::acquire_gil();
    let py = gil.python();
    py.run(r#"
import sys
from multiprocessing import Process

def f(name):
    print('hello', name)

if __name__ == '__main__':
    print('start')
    sys.argv=['']
    p = Process(target=f, args=('bob',))
    p.start()
    p.join()
    "#, None,None).unwrap();
}

Вывод (продолжается до Ctrl- C):

start
start
start
start
start
start
start
start

РЕДАКТИРОВАТЬ

Как упоминалось в комментариях ниже, я перестал пытаться создавать процессы из кода Python. Помехи между Windows, Python модулем многопроцессорной обработки и тем, как процессы создаются с помощью Rust, слишком неясны для правильного управления. Поэтому вместо этого я буду создавать и управлять ими из Rust. Код, следовательно, больше учебник:

use std::process::Command;
fn main() {
    let mut cmd = Command::new("python");
    cmd.args(&["-c", "print('test')"]); 
    let process = cmd.spawn().expect("Couldn't spawn process.");
    println!("{:?}", process.wait_with_output().unwrap());
}

1 Ответ

0 голосов
/ 25 февраля 2020

Я не могу воспроизвести это; для меня это просто печатает start и затем hello bob, как и ожидалось. По какой-то причине кажется, что в вашем случае __name__ всегда равно "__main__", и вы получаете эту бесконечную рекурсию. Я использую cpython ящик версии v0.4.1 и Python 3.8.1 на Arch Linux.

Обходной путь должен вообще не зависеть от __name__, но для вместо этого определите свой код Python как модуль с функцией main(), а затем вызовите эту функцию:

use cpython::{Python, PyModule};

fn main() {
    let gil = Python::acquire_gil();
    let py = gil.python();
    let module = PyModule::new(py, "bob").unwrap();
    py.run(r#"
import sys
from multiprocessing import Process

def f(name):
    print('hello', name)

def main():
    print('start')
    sys.argv=['']
    p = Process(target=f, args=('bob',))
    p.start()
    p.join()
    "#, Some(&module.dict(py)), None).unwrap();
    module.call(py, "main", cpython::NoArgs, None).unwrap();
}
...