我正在开发一个在Windows系统下具有不寻常框架的项目:c++ main()通过C API调用Python Multiprocessing函数。该框架无需多处理即可正常运行。一旦使用多处理模块(即使只有 1 个进程),程序就会不断添加新的 c++ main() exe 进程。 Python 脚本独立与所使用的多处理模块配合良好。 我认为这与多处理模块的实现有关;网上查遍都没有找到相关信息。有人可以提供一些提示吗?谢谢!
开始.py
import time
import multiprocessing as mp
def do_something():
print('Sleeping 1 second...')
time.sleep(1)
print('Done Sleeping...')
def benchmark():
start = time.perf_counter()
p1 = mp.Process(target=do_something)
p2 = mp.Process(target=do_something)
p1.start()
#p2.start()
p1.join()
#p2.join()
finish = time.perf_counter()
print(f'Finished in {round(finish - start,2)} second(s)')
if __name__ == '__main__':
benchmark()
callPythonFromCpp.cpp
#include <Windows.h>
#include <iostream>
#include <string>
#include <Python.h>
using namespace std;
void CallPython(string PythonModuleName, string PythonFunctionName)
{
char* funcname = new char[PythonFunctionName.length() + 1];
strcpy_s(funcname, PythonFunctionName.length() + 1, PythonFunctionName.c_str());
char* modname = new char[PythonModuleName.length() + 1];
strcpy_s(modname, PythonModuleName.length() + 1, PythonModuleName.c_str());
// Initialize the Python interpreter
Py_Initialize();
PyObject* my_module = PyImport_ImportModule(modname);
PyObject* my_function = PyObject_GetAttrString(my_module, funcname);
// Call a callable Python object callable, with arguments given by the tuple args.
// If no arguments are needed, then args can be NULL.
PyObject* my_result = PyObject_CallObject(my_function, NULL);
// Undo all initializations made by Py_Initialize() and subsequent use of Python/C API functions,
// and destroy all sub-interpreters (see Py_NewInterpreter() below) that were created and not yet
// destroyed since the last call to Py_Initialize(). Ideally, this frees all memory allocated by the Python interpreter.
Py_Finalize();
delete[] funcname;
delete[] modname;
}
int main()
{
CallPython("start", "benchmark");
system("pause");
return 0;
}
更新: 在Python代码中打印sys.executable和os.getpid(); 当调用 p1.start() 时,会递归调用 C++ main() 的新进程。 我认为这与多处理如何识别主进程和子进程有关。例如,Python 独立版具有“if name == 'main'”,这对于使用多处理模块至关重要。
Python 更新:
def benchmark():
start = time.perf_counter()
p1 = mp.Process(target=do_something)
p2 = mp.Process(target=do_something)
print('sys.executable: ' + sys.executable + '\n')
print('os pid: ' + str(os.getpid()) + '\n')
p1.start()
#p2.start()
#p1.join()
#p2.join()
finish = time.perf_counter()
print(f'Finished in {round(finish - start,2)} second(s)')
终端输出:
sys.executable: C:\Users\xxx\source\repos\callPythonFromCpp\x64\Release\callPythonFromCpp.exe
os pid: 25408
Finished in 0.08 second(s)
sys.executable: C:\Users\xxx\source\repos\callPythonFromCpp\x64\Release\callPythonFromCpp.exe
os pid: 32332
Finished in 0.01 second(s)
sys.executable: C:\Users\xxx\source\repos\callPythonFromCpp\x64\Release\callPythonFromCpp.exe
os pid: 9456
Finished in 0.01 second(s)
sys.executable: C:\Users\xxx\source\repos\callPythonFromCpp\x64\Release\callPythonFromCpp.exe
os pid: 8944
更新2023-11-23 关注这篇文章 嵌入式 python:多处理不起作用 我的程序现在可以运行了。 C++代码保持不变; Python代码如下:
import time
import multiprocessing as mp
def do_something():
print('Sleeping 1 second...')
time.sleep(1)
print('Done Sleeping...')
def benchmark():
sys.argv = [r'C:\path_to_this\start.py']
mp.set_executable(r'C:\path_to_Python_install\python.exe')
start = time.perf_counter()
p1 = mp.Process(target=do_something)
p2 = mp.Process(target=do_something)
p1.start()
p2.start()
p1.join()
p2.join()
finish = time.perf_counter()
print(f'Finished in {round(finish - start,2)} second(s)')
if __name__ == '__main__':
benchmark()
import time
import multiprocessing as mp
def do_something():
print('Sleeping 1 second...')
time.sleep(1)
print('Done Sleeping...')
def benchmark():
sys.argv = [r'C:\path_to_this\start.py']
mp.set_executable(r'C:\path_to_Python_install\python.exe')
start = time.perf_counter()
p1 = mp.Process(target=do_something)
p2 = mp.Process(target=do_something)
p1.start()
p2.start()
p1.join()
p2.join()
finish = time.perf_counter()
print(f'Finished in {round(finish - start,2)} second(s)')
还有另一个潜在的问题:如果 python 代码中存在多处理代码,我们无法对所有 python 代码进行 cythonize;磁盘上必须有一个 .py 文件供多处理模块解析。请参阅这篇文章: