【发布时间】:2020-02-27 16:48:14
【问题描述】:
我使用 Rust 来加速数据处理管道,但我必须按原样运行一些现有的 Python 代码,我想并行化这些代码。在另一个question 中讨论之后,考虑到我的项目的特定限制,创建多个 Python 进程是一种可能的方法。但是,运行下面的代码会产生无限循环。我不太明白为什么。
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
编辑
正如下面的 cmets 所述,我放弃了尝试从 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());
}
【问题讨论】:
-
我无法重现这个。使用最新的 cpython crate (v0.4.1) 和最新的 Python (3.8.1)。
-
我想
__name__在您的情况下始终设置为"__main__",即使在您的子流程中也是如此。您可以通过将该代码放入 Python 中的main()函数中并按照 this example 从 Rust 调用该函数来解决此问题。 -
你是对的。我在python代码中添加了
print(__name__),每个进程打印__main__。如果我在纯 Python 中运行代码,子进程中的__name__是__mp_main__,它可以防止循环。我检查了您发送的链接,但不明白如何将其应用于我的示例。 -
把所有
__main__的东西都抽出来并做一个print(hello)不会有什么坏处。您也不需要if main- 它可以防止在导入时执行代码,这对您来说不是必需的。一旦打印工作,尝试添加子进程。关键是,尽可能简化python端,然后重新构建它。如果你有问题,你知道你需要修复 rust call config。如果没有,请逐渐添加最少的代码以在 python 上构建您想要的解决方案, -
你在windows上,不是吗?