我让它工作(在 Linux 上)执行以下操作:
// method to inspect PyObjects
static void reprint(PyObject *obj)
{
PyObject* repr = PyObject_Repr(obj);
PyObject* str = PyUnicode_AsEncodedString(repr, "utf-8", "~E~");
const char *bytes = PyBytes_AS_STRING(str);
printf("REPR: %s\n", bytes);
Py_XDECREF(repr);
Py_XDECREF(str);
}
.
int main()
{
// for our manually compiled and installed usr-local Python 3.6
//#define PATH L"/usr/local/bin:/usr/local/lib:/usr/local/lib/python3.6/lib-dynload"
//#define PREFIX L"/usr/local"
//#define EXEC_PREFIX L"/usr/local"
//#define FULL_PROG_PATH L"/usr/local/bin/python3.6"
// for apt installed Python 3.7
//#define PATH L"/usr/bin:/usr/lib:/usr/lib/python3.7/lib-dynload"
//#define PREFIX L"/usr"
//#define EXEC_PREFIX L"/usr"
//#define FULL_PROG_PATH L"/usr/bin/python3.7"
// for venv (which uses the /usr/local/lib python 3.6)
#define PATH L"/home/me/venv_dir/bin:/home/me/venv_dir/lib:/usr/local/lib/python3.6:/usr/local/lib/python3.6/lib-dynload"
#define PREFIX L"/home/me/venv_dir"
#define EXEC_PREFIX L"/usr/local"
#define FULL_PROG_PATH L"/usr/local/bin/python3.6"
// ------------------------------------------------
#define CHANGE_THE_INTERPRETER
#ifdef CHANGE_THE_INTERPRETER
// TODO : Look at using this: https://www.python.org/dev/peps/pep-0587/
Py_SetPath(PATH);
// change the built-in prefix/exec-prefix, in place.
wchar_t* wpPrefix = Py_GetPrefix();
wchar_t* wpExecPrefix = Py_GetExecPrefix();
wchar_t* wpProgramFullPath = Py_GetProgramFullPath();
wcscpy (wpPrefix, PREFIX);
wcscpy (wpExecPrefix, EXEC_PREFIX);
wcscpy (wpProgramFullPath, FULL_PROG_PATH);
#endif //CHANGE_THE_INTERPRETER
// inspect the environment variables. With the #define commented out above the "defaults" appear as indicated to the right hand side
wchar_t* xx; //defaults
xx = Py_GetPrefix(); //<prefix> L"/usr/local"
xx = Py_GetExecPrefix(); //<exec_prefix> L"/usr/local"
xx = Py_GetPath(); //L"/usr/local/lib/python36.zip:/usr/local/lib/python3.6:/usr/local/lib/python3.6:/usr/local/lib/python3.6/lib-dynload"
xx = Py_GetProgramName(); //L"python3"
xx = Py_GetPythonHome(); //null
xx = Py_GetProgramFullPath(); //<progpath> L"/usr/local/bin/python3"
Py_Initialize();
一些额外的位
int x2 = PyRun_SimpleString ("import site; print (site.getsitepackages())");
int x3 = PyRun_SimpleString ("import datetime");
int x4 = PyRun_SimpleString ("import numpy as np");
//inspect sys info
PyObject* sys_executable = PySys_GetObject((char*)"executable"); reprint(sys_executable);
PyObject* sys_version = PySys_GetObject((char*)"version"); reprint(sys_version);
PyObject* sys_realPrefix = PySys_GetObject((char*)"real_prefix"); reprint(sys_realPrefix);
PyObject* sys_basePrefix = PySys_GetObject((char*)"base_prefix"); reprint(sys_basePrefix);
需要注意的几点:
如果您查看 Python 模块 getpath.c,您将看到以下缓冲区:
static wchar_t prefix[MAXPATHLEN+1];
static wchar_t exec_prefix[MAXPATHLEN+1];
static wchar_t progpath[MAXPATHLEN+1];
Py_GetProgramFullPath等方法执行如下:
if (!module_search_path)
calculate_path();
return progpath;
...所以可以使用这些方法来获取缓冲区指针和wcscpy 直接将值放入缓冲区。 请注意,目前只有以这种方式实现 getpath 才有可能!
需要lib-dynload来保证某些模块(例如日期时间)可以拉入
另请注意,此方法可确保可以找到 .../python3.x/encodings 目录,从而防止 Py_Initialize 中出现运行时错误