使用 Python 3 加载 Python 模块失败

Fails to load Python module with Python 3

#include <Python.h>
#include <fstream>
#include <iostream>
#include <string>
#include <filesystem>
#include <sys/types.h>

#include <dirent.h>


static const char * sPythonCode =
"class Test :\n"
"   def __init__(self) : \n"
"     self.Disc_ = 0. \n"
"   def getset(self) : \n"
"     self.Disc_ = 7. \n"
"     return self.Disc_ \n";


std::string writeFile()
{
   static int iFile = 0;
   std::string sFileName(std::string("test") + std::to_string(iFile));
   std::ofstream out("py/" + sFileName + ".py");
   out << sPythonCode;
   out.flush();
   out.close();
   iFile++;
   return sFileName;
}

static bool bPythonOpen = false;
#define PYTHONPATHLEN 501

static void _PyInit()
{
   if (!Py_IsInitialized())
   {
      Py_InitializeEx(0);
   }
}

void openPython(void)
{
   if (!bPythonOpen)
   {
      const size_t szBufferN = 1000;
      char acLoadPath[szBufferN];
      const char *pypath = "./py";

      _PyInit();

      PyRun_SimpleString("import sys");
      PyRun_SimpleString("print('python (%d.%d.%d) initialized' % (sys.version_info.major, sys.version_info.minor, sys.version_info.micro))");
      PyRun_SimpleString("print('--------------------------')");


      snprintf(acLoadPath, szBufferN, "sys.path.append('%s')", pypath);
      PyRun_SimpleString(acLoadPath);

      bPythonOpen = true;
   }
}

PyObject *loadPythonModule(const char *acModule)
{
   PyObject *pyModule = NULL;

   if (bPythonOpen && acModule && strcmp(acModule, ""))
   {
      printf("%s\n", acModule);
      pyModule = PyImport_ImportModule(acModule);
      if (!pyModule)
      {
         PyErr_Print();
      }
   }
   return pyModule;
}

void loadPython()
{

   std::string sFileName = writeFile();

   openPython();
   //sleep(1);
   PyObject *pPythonModule = loadPythonModule(sFileName.c_str());
   
   if (pPythonModule)
      PyDict_DelItemString(PyImport_GetModuleDict(), PyModule_GetName((PyObject *)pPythonModule));
}

int main(int argc, char **argv)
{
   for (int i = 0; i < 10; i++)
   {     
      loadPython();
   }
}

我的工作环境:

编译命令:

g++ pythontest.cpp -I/opt/python/python3.6.10/include/python3.6m -L/opt/python/python3.6.10/lib -lpython3.6m

创建py目录:

mkdir py

当我 运行 这段代码时,我加载的不同测试文件出现随机错误。

输出示例:

python (3.6.10) initialized
--------------------------
test0
test1
test2
test3
ModuleNotFoundError: No module named 'test3'
test4
test5
ModuleNotFoundError: No module named 'test5'
test6
test7
ModuleNotFoundError: No module named 'test7'
test8
test9
ModuleNotFoundError: No module named 'test9'

很高兴知道:

目前 Python 加载程序似乎没有看到磁盘上的文件,但是如果我打印目录中的内容失败,由于 dirent,我会看到 testx.py

请注意,我们在不同的 Linux 服务器上重现了错误(不是硬件问题,甚至在 Windows 上),Python 2.7.x 它有效非常好。

每次修改模块文件夹时都应该调用 __import__('importlib').invalidate_caches() 让 C Python 知道它必须再次读取目录。