Получение встроенной среды исполнения Python для использования текущего активного virtualenv

Я активно использую virtualenv для изоляции своих сред разработки от общесистемной установки Python. Типичный рабочий поток для использования virtualenv включает запуск

source /path/to/virtualenv/bin/activate
для установки переменных среды, которые Python требует для выполнения изолированной среды выполнения. Убедитесь, что мои исполняемые файлы Python используют текущий активный virtualenv, так же просто, как установка shebang на
#!/usr/bin/env python
Тем не менее, в последнее время я написал код C, который внедряет среду выполнения Python. Я не могу понять, как заставить встроенную среду выполнения использовать текущий активный virtualenv. Кто-нибудь получил хороший пример для обмена?

Спасибо!

Ответ 1

Проверка пути и настройка Py_SetProgramName работали для меня:

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();

Ответ 2

Кажется, это не ответ, но может быть полезен и в других контекстах.

Попробовали ли вы запустить bin/activate_this.py из своего виртуального виджета Python? Комментарий в этом файле моего virtualenv гласит:

Используя execfile(this_file, dict(__file__=this_file)), вы активируйте эту виртуальную среду.

Это можно использовать, когда вы должны использовать существующий интерпретатор Python, а не virtualenv bin/python

Вы должны достичь желаемого результата, если вы выполняете эквивалент выполнения, указанный выше.

Ответ 3

Ну, C API docs подразумевает, что он должен просто работать (я читал его как неопределенное намека на то, что интерпретатор сам вызывает getenv), но кажется, не хватает достаточного контекста, чтобы быть уверенным, и у меня никогда не было возможности проверить это.

Поскольку он, по-видимому, не работает для вас, то, что вы действительно ищете, вероятно, будет Py_SetPythonHome(char *home), который вам нужно просто нужно позвонить с копией строки, которую вы получаете от getenv("PYTHONHOME").

Вы можете, конечно, также изменить sys.path на эффект PYTHONPATH, если это необходимо.

Ответ 4

Из http://docs.python.org/release/1.5.2/api/embedding.html кажется, что он будет работать только до тех пор, пока ваш PATH имеет каталог virtualenv до предварительно установленных версий python. Если нет, попробуйте установить PYTHONHOME, как упомянуто Николасом Найт.

Ответ 5

Вы можете проверить переменную окружения VIRTUAL_ENV, чтобы получить текущее местоположение envs.

Ответ 6

Я обнаружил, что ответ @dikobraz не работает для меня в mac OSX venvs, потому что даже после установки PythonProgName префикс, а затем PythonHome по-прежнему были неправильно установлены в системные каталоги python.

Что для меня работало, было:

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

перед запуском Py_Initialize().