最近需要写一个从c++导入python库,并获取python脚本中的变量和函数。
刚开始测试时,python脚本和exe在同一目录,都比较正常。但是当脚本与exe不再同一目录是,总提示ImportError
例如,我的exe目录是:D:\test\pythonEmb\Debug,而脚本mymodule.py在其子目录aa下;
命令行尝试:testpythonemb aa.mymodule或者testpythonemb mymodule均提示importError
//testpythonemb.cpp
int main(int argc, char *argv[])
{
PyObject *pName, *pModule;
PyObject *pArgs;
int i;
if (argc < 2) {
fprintf(stderr,"Usage: testpythonemb pythonfile\n");
return 1;
}
Py_SetProgramName(argv[0]);
printf("arg[1]=%s\n", argv[1]);
Py_Initialize();
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('D:\\test\\pythonEmb\\Debug\\aa')");
pName = PyString_FromString(argv[1]);
pModule = PyImport_Import(pName);
Py_DECREF(pName);
if (pModule != NULL) {
pArgs = PyObject_GetAttrString(pModule, "ArgNameList");
PyObject* arg_dict = PyDict_New();
if (pArgs)
{
Py_ssize_t len = PyObject_Length(pArgs);
printf("len = %d\n", len);
for (Py_ssize_t i = 0; i < len; i++)
{
PyObject* pKey = PyInt_FromLong(i);
PyObject* pItem = PyObject_GetItem(pArgs, pKey);
printf("%s\n", PyString_AsString(pItem));
PyDict_SetItem(arg_dict, pItem, pKey);
Py_DECREF(pKey);
Py_DECREF(pItem);
}
}
Py_XDECREF(pArgs);
PyObject_SetAttrString(pModule,"arg_dict",arg_dict);
PyObject *pFunc = PyObject_GetAttrString(pModule, "print_arg_info");
if (pFunc && PyCallable_Check(pFunc))
{
PyObject_CallObject(pFunc, NULL);
}
Py_DECREF(arg_dict);
Py_DECREF(pModule);
}
else {
PyErr_Print();
return 1;
}
Py_Finalize();
return 0;
}
后来将
PyRun_SimpleString("sys.path.append('D:\\test\\pythonEmb\\Debug\\aa')");
改为:
PyRun_SimpleString("sys.path.append('D:/test/pythonEmb/Debug/aa')");
后,testpythonemb mymodule
执行正常,问题得到解决。
由于好奇,我直接启动python,导入sys模块后,看了一下sys.path,里面的路径也是windows格式的,我想不明白,在我的代码中设置windows格式的目录为什么不行。
另外,想试试能不能通过python包的方式导入module,
就仅将exe的路径添加到sys.path中,如下:
PyRun_SimpleString("sys.path.append('D:/test/pythonEmb/Debug')");
然后执行:
testpythonemb aa.mymodule
或者testpythonemb mymodule
, 均提示importError;
那么,如果想要命令testpythonemb aa.mymodule
能执行成功,需要怎么做呢?此问题暂时没有找到答案,后续有解决方案后再补充。
附上mymodule.py的代码:
#mymodule.py
ArgNameList = ["enbid", "cellid", "uegid", "erabtype"]
arg_dict = {}
def get_arg(key):
if key in arg_dict.keys():
return arg_dict[key]
return None
def print_arg_info():
for key in arg_dict.keys():
print("{} = '{}'".format(key, arg_dict[key]))