是否可以在運行時修改PYTHONPATH ?

[英]Is it possible to modify PYTHONPATH at runtime?


I have a C++ application dynamically linked to the Python interpreter. I want to be able to import python modules from a particular directory. I want to modify the PYTHONPATH for my process so that sys.path will include the paths that I added to the PYTHONPATH. That seems to be the way it works according to this documentation:

我有一個動態鏈接到Python解釋器的c++應用程序。我希望能夠從一個特定的目錄導入python模塊。我想要為我的進程修改PYTHONPATH,這樣系統。path將包含我添加到PYTHONPATH中的路徑。這似乎是它的工作方式根據這個文件:

http://docs.python.org/c-api/intro.html#embedding-python

http://docs.python.org/c-api/intro.html embedding-python

However, when I print sys.path from Python-land it has the original contents of PYTHONPATH and not the one I set. Here's an example of what I'm doing (using Boost.Python):

但是,當我打印sys時。它包含了PYTHONPATH的原始內容,而不是我設置的。

int main(int argc, char* argv[])
{
  _putenv_s("PYTHONPATH", "C:\\source\\\\modules");
  Py_Initialize();
  object main = import("__main__");
  object global = (main.attr("__dict__"));
  exec("import sys\nprint sys.path"), global, global);
}

PS - I know there are other ways to accomplish my goal, but that's not what I'm asking about. I am wondering why Py_Initialize() doesn't use the current value of PYTHONPATH when setting up sys.path. Or perhaps I've misunderstood how it is supposed to work?

我知道還有其他方法可以實現我的目標,但這不是我想要的。我想知道為什么Py_Initialize()在設置sys.path時不使用PYTHONPATH的當前值。或許我誤解了它的工作原理?

7 个解决方案

#1


7  

I found cross-platform solution. Before invoke any other python code just execute following python lines:

我發現跨平台解決方案。在調用任何其他python代碼之前,請執行以下python行:

import sys
sys.path.append("C:\\source\\\\modules")

#2


3  

This happens if you're using more than one C runtime library at a time. In this case, your application and the Python DLL are probably linked against different CRTs. Each CRT has its own set of environment variables; changes to the environment made with putenv from one CRT are not visible from getenv calls made with a different CRT.

如果一次使用多個C運行時庫,就會發生這種情況。在這種情況下,您的應用程序和Python DLL可能被鏈接到不同的crt上。每個CRT都有自己的環境變量集;使用一個CRT對putenv進行的環境更改從使用另一個CRT進行的getenv調用中看不到。

See the "readEnv" example at http://msdn.microsoft.com/en-us/library/ms235460%28v=vs.80%29.aspx.

請參見http://msdn.microsoft.com/en- us/library/ms2354600% 28v=vs.8029.aspx的“readEnv”示例。

You can fix this by making sure to use only a single CRT, but that's tricky in practice. Debug builds of programs typically use debug CRTs (which enable things like heap checks and API assertions); production DLLs, even when used in debugging, typically use MSVCRT, the production, threadsafe version. I've worked around this by disabling the debug CRTs entirely, setting all builds to "multithreaded dynamic", since maintaining separate debug DLLs is too much of a hassle. You lose some debugging capabilities by doing that.

您可以通過確保只使用一個CRT來解決這個問題,但這在實踐中是很棘手的。程序的調試構建通常使用調試crt(它支持堆檢查和API斷言);生產dll,即使在調試中使用,通常也使用MSVCRT,即生產的threadsafe版本。我通過完全禁用調試crt來解決這個問題,將所有的構建設置為“多線程動態”,因為維護單獨的調試dll實在是太麻煩了。這樣做會丟失一些調試功能。

#3


3  

Check out:

查看:

void PySys_SetPath(char *path) Set sys.path to a list object of paths found in path which should be a list of paths separated with the platform’s search path delimiter (: on Unix, ; on Windows).

void PySys_SetPath(char *path)路徑中找到的路徑列表對象的路徑,該路徑應該是與平台的搜索路徑分隔符(:Unix上;在Windows上)。

or

Py_SetProgramName(argv[0]); That adds dirname(argv[0]) to your PYTHONPATH for you.

Py_SetProgramName(argv[0]);它為您將dirname(argv[0])添加到python路徑中。

#4


2  

As other people have said, you may be running into a CRT mismatch. I was able to get this to work with Python 2.6 and Visual C++ 2008:

正如其他人所說,您可能會遇到CRT不匹配。我能夠讓它與Python 2.6和Visual c++ 2008一起工作:

#include "stdafx.h"
#include "Python.h"

int _tmain(int argc, _TCHAR* argv[])
{
  _putenv_s("PYTHONPATH", "C:\\source\\\\modules");
  Py_Initialize();
  PyRun_SimpleString("import sys\nprint sys.path");
  PyRun_SimpleString("raw_input()");
  return 0;
}

This output:

這個輸出:

['C:\\Python26\\lib\\site-packages\\distribute-0.6.13-py2.6.egg', 'C:\\Python26\
\lib\\site-packages\\virtualenv-1.4.9-py2.6.egg', 'C:\\source\\modules', ...

Another option may be to change to that directory, since the current directory typically ends up on the path, e.g.:

另一種選擇可能是更改到該目錄,因為當前目錄通常在路徑上結束,例如:

    _chdir("c:\\");
    Py_Initialize();
[...]

which gives me:

給我:

['C:\\Python26\\lib\\site-packages\\distribute-0.6.13-py2.6.egg', 'C:\\Python26\
\lib\\site-packages\\virtualenv-1.4.9-py2.6.egg', 'C:\\Windows\\system32\\python
26.zip', 'C:\\Python26\\Lib', 'C:\\Python26\\DLLs', 'C:\\Python26\\Lib\\lib-tk',
 'c:\\', ...

#5


1  

It is possible that the Python DLL gets its own copy of the environment when it is loaded. Try loading it with LoadLibrary and GetProcAddress after you've changed the environment and see if that changes anything.

在加載環境時,Python DLL可能獲得它自己的環境副本。在更改了環境之后,嘗試使用LoadLibrary和GetProcAddress加載它,看看這是否會改變什么。

#6


1  

#include "Python.h"
int main()
{
  Py_Initialize();
  PyRun_SimpleString("import sys");
  PyRun_SimpleString("sys.path.append(\"<some_path>\")");
  return 0;
}

This worked for all python version (2.6, 2.7, 3.1, 3.2, 3.3 and 3.4).
Several notes regarding <some_path>:

這適用於所有python版本(2.6、2.7、3.1、3.2、3.3和3.4)。一些筆記關於< some_path >:

  • It should contain only a single directory. List of directories with valid separators (d:/path1;d:/path2 etc.) is not working
  • 它應該只包含一個目錄。有有效分隔符的目錄列表(d:/path1;d:/path2等)無效
  • Windows paths like: d:\\path1 will work only for python versions prior to Python 3, for later versions d:\\\\path1 should be used. I'd advice replacing windows path delimiters with unix delimiters. Following code chunk does this.

    Windows路徑如:d:\ path1只適用於python 3之前的python版本,適用於以后的版本d:\\\ path1。我建議用unix分隔符替換windows路徑分隔符。下面的代碼塊可以做到這一點。

    std::string my_path = "<some_path>"; std::replace(my_path.begin(), my_path.end(), '\\', '/');

    std::string my_path = " < some_path >”;std::替換(my_path.begin(),my_path.end(),' \ \ ',' / ');

A gentle advise: Don't waste your time trying to modify PYTHONPATH with either of the following API methods if you want to support different python versions:

一個溫和的建議:如果您希望支持不同的python版本,請不要浪費時間嘗試使用以下任何一種API方法修改PYTHONPATH:

  • Py_SetPythonHome() - for python 2 requires an ascii string, for python 3 - a unicode string, but doesn't work reliably for versions greater than 3.1
  • Py_SetPythonHome()——對於python 2,需要一個ascii字符串;對於python 3,需要一個unicode字符串;但是對於大於3.1的版本,它不能可靠地工作
  • Py_SetPath() - introduced in python 3, but is buggy (see http://bugs.python.org/issue11320)
  • Py_SetPath()——在python 3中引入,但是有bug(參見http://bugs.python.org/issue11320)

In general API methods listed above do not affect after Py_Initialize() call.

在一般情況下,上面列出的API方法不會影響Py_Initialize()調用之后的API。

#7


1  

You could just do python3 -c "import sys; sys.path.append('C:\Path\To\Modules')"

你可以用python3 -c "import sys;sys.path.append(“C:\路徑\ \模塊”)”


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2011/03/15/c0e041cebf77b53c2529a62921dcc7cf.html



 
  © 2014-2022 ITdaan.com 联系我们: