Для встраивания python в мое приложение cpp я скомпилировал cpython 3.7.3 для Windows с MSVC v141 из VS2017 (MSV v.1916 32bit).Сгенерированный код помещается в PCBuild / win32.
Приложение должно изменить sys.path
, чтобы найти модули из подпапок каталога приложения.Вот где я заметил сбой, который я не могу объяснить.Следующий скрипт работает при первом запуске, но не при втором.Второй запуск приводит к сбою приложения.Это связано с оператором import
.Я могу легко вызывать реальные функции opencv, но убрал это для минимального примера.Кроме того, скрипт не падает, если я удаляю C:\Python\cpython3.7.3\PCbuild\win32
из пути поиска, но, конечно, скрипт не будет делать то, что должен.
#!/usr/bin/env python3
import sys
sys.path = ['', 'C:\Python\cpython3.7.3', 'C:\Python\cpython3.7.3\Lib', 'C:\Python\cpython3.7.3\PCbuild\win32', 'C:\Python\cpython3.7.3\Lib\site-packages']
import cv2 # crash on 2nd run
import numpy # crash on 2nd run
import os # always works
import glob # always works
К сожалению, я не могу отладить приложение при запускеpython, потому что python не может инициализироваться из-за отсутствующих кодировок.Работает только режим релиза.Кажется, что встроенные модули работают, а загруженные через pip (папка site-packages) не работают.
Шаги
- Сохраните скрипт Python сверху на C:/temp/import_crash_on_2nd_run.py
- Загрузить cpython в C: /python/cpython3.7.3
- Поместить build.bat в C: / python с содержимым ниже и запустить этот файл.Здание занимает ок.5 минут.
build.bat: (выпустить сборку; для отладки добавить -d)
cd cpython3.7.3
cd PCbuild
cmd /c build.bat
pause
Чтобы выполнить скрипт, я создал этот минимальный пример.Это не мой оригинальный код, но он также дает сбой при втором запуске, я ожидаю, что причина будет той же.
main.cpp
#include <Python.h>
#include <fstream>
#include <sstream>
#include <string>
int runScript(const std::string &script){
const char *script_ = {script.c_str()};
Py_Initialize();
PyRun_SimpleString(script_);
Py_Finalize();
return 0;
}
int main(int argc, char *argv[])
{
std::string scriptpath = "C:\\temp\\import_crash_on_2nd_run.py";
std::ifstream t(scriptpath);
std::stringstream buffer;
buffer << t.rdbuf();
// maxCount=2 -> crash
int maxCount = 1;
for ( int count = 0; count < maxCount; count++ ){
runScript(buffer.str());
}
}
ОБНОВЛЕНИЕ:
Это ошибка.Кто-то в https://github.com/numpy/numpy/issues/8097 заметил, что, если вы не позвоните Py_Finalize
, при последовательном импорте не произойдет сбой.Хотя не об этом.Не уверен, что это ошибка Python или плохое качество из используемых библиотек.