开发者

Getting an embedded Python runtime to use the current active virtualenv

I make heavy use of virtualenv to isolate my development environments from the system-wide Python installation. Typical work-flow for using a virtualenv involves running

source /path/to/virtualenv/bin/activate
to set the environment variables that Python requires to execute an isolated runtime. Making sure my Python executables use the current active virtualenv is as simple as setting the shebang to
#!/usr/bin/env python

Lately, though, I've been writing some C code that embeds the Python runtime. What I can't seem to figure out is how to get the embedded runtime to use t开发者_StackOverflow社区he current active virtualenv. Anybody got a good example to share?


Inspecting path and setting Py_SetProgramName worked for me:

std::vector<std::string> paths;
std::string pathEnv = getenv("PATH");
boost::split(paths, pathEnv, boost::is_any_of(";:"));
for (std::string path : paths)
{
  boost::filesystem::path pythonPath = boost::filesystem::path(path) / "python";
  std::cout << pythonPath << std::endl;
  if (boost::filesystem::exists(pythonPath))
  {
    pythonProgramName_ = pythonPath.string(); // remember path, because Py_SetProgramName doesn't save it anywhere
    Py_SetProgramName(&pythonProgramName_[0]);
    break;
  }
}
Py_Initialize();


Seems to be not an answer, but still might be useful in other contexts.

Have you tried running bin/activate_this.py from your Python virtualenv? The comment in this file of my virtualenv reads:

By using execfile(this_file, dict(__file__=this_file)) you will activate this virtualenv environment.

This can be used when you must use an existing Python interpreter, not the virtualenv bin/python

You should achieve the desired result if you execute the runtime equivalent of the above code.


I found that @dikobraz's answer did not work for me on mac OSX venvs because even after setting PythonProgName, the prefix and then PythonHome were still incorrectly set to system python directories.

What worked for me instead was:

if (auto venv_path = std::getenv("VIRTUAL_ENV")) {
    setenv("PYTHONHOME", venv_path, true);
}

before running Py_Initialize().


Well, the C API docs kind of imply it should just work (I read it as vaguely hinting the interpreter calls getenv itself), but seem to lack sufficient context to be certain, and I've never had occasion to actually test that.

Since it's apparently not working for you, what you're really looking for is probably going to be Py_SetPythonHome(char *home), which you should just need call with a copy of the string you get from getenv("PYTHONHOME").

You can, of course, also modify sys.path for the effect of PYTHONPATH, if needed.


From http://docs.python.org/release/1.5.2/api/embedding.html it seems that it will just work as long as your PATH has the virtualenv directory before the pre-installed python versions. If not, try setting PYTHONHOME as mentioned by Nicholas Knight.


You can the check the environment variable VIRTUAL_ENV to get the current envs location.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜