让Python使用Py_SetPath()在不同位置查找Lib

问题描述 投票:0回答:2

我已将 Python 嵌入到应用程序中,

foo.exe
。 当它运行时,Python 被调用并立即查找
Lib
。 我让它工作的唯一方法是将
Lib
(Python 的模块目录库)放在
foo.exe
的位置。

有没有办法可以将 Python 重定向到其他地方,例如

Python/Lib
? 我无法更改
PATH
(这是Windows)并且我不想破解Python源代码。

基本上,我无法让 Py_SetPath() 工作,并且我无法在互联网上找到任何实际示例。

更新:

好的,这有效:

  #define MYMAXPATHLEN 1000
  static wchar_t progpath[MYMAXPATHLEN + 1];

  wchar_t* pdir = L"\\My_New_Location\\Python\\Lib";
  wchar_t* pdelim = L";";
  wchar_t* pypath = NULL;
  GetModuleFileNameW(NULL, progpath, MYMAXPATHLEN);
  reduce(progpath);
  wcscat(progpath,pdir);
  // I get the present module path and add the extra dirs to access Lib code

  wcscat(progpath, pdelim);  // I add a path delimiter

  pypath = Py_GetPath();
  wcscat(progpath, pypath);
  // I add the paths that Py_GetPath() produces.

  Py_SetPath(progpath);

  Py_Initialize();

我还调用 Py_SetProgramName(); Py_Initialize() 之后; 我不确定是否需要所有这些额外的东西,但较小的解决方案似乎失败了。

初始化后调用 Py_SetProgamName() 似乎对于嵌入调用正常工作非常重要。

python python-3.x python-module
2个回答
2
投票

在导入库之前,运行以下行:

sys.path.append('C:\path to Lib')

详情请参阅这里


1
投票

我让它工作(在 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

中出现运行时错误
© www.soinside.com 2019 - 2024. All rights reserved.