Сбой встроенного питона при втором запуске - PullRequest
0 голосов
/ 15 апреля 2019

Для встраивания 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 или плохое качество из используемых библиотек.

...