Nothing
#' Use Python
#'
#' Select the version of Python to be used by `reticulate`.
#'
#' The `reticulate` package initializes its Python bindings lazily -- that is,
#' it does not initialize its Python bindings until an API that explicitly
#' requires Python to be loaded is called. This allows users and package authors
#' to request particular versions of Python by calling `use_python()` or one of
#' the other helper functions documented in this help file.
#'
#' @section RETICULATE_PYTHON:
#'
#' The `RETICULATE_PYTHON` environment variable can also be used to control
#' which copy of Python `reticulate` chooses to bind to. It should be set to
#' the path to a Python interpreter, and that interpreter can either be:
#'
#' - A standalone system interpreter,
#' - Part of a virtual environment,
#' - Part of a Conda environment.
#'
#' When set, this will override any other requests to use a particular copy of
#' Python. Setting this in `~/.Renviron` (or optionally, a project `.Renviron`)
#' can be a useful way of forcing `reticulate` to use a particular version of
#' Python.
#'
#' @section Caveats:
#'
#' Note that the requests for a particular version of Python via `use_python()`
#' and friends only persist for the active session; they must be re-run in each
#' new \R session as appropriate.
#'
#' If `use_python()` (or one of the other `use_*()` functions) are called
#' multiple times, the most recently-requested version of Python will be
#' used. Note that any request to `use_python()` will always be overridden
#' by the `RETICULATE_PYTHON` environment variable, if set.
#'
#' The [py_config()] function will also provide a short note describing why
#' `reticulate` chose to select the version of Python that was ultimately
#' activated.
#'
#' @param python
#' The path to a Python binary.
#'
#' @param version
#' The version of Python to use. `reticulate` will search for versions of
#' Python as installed by the [install_python()] helper function.
#'
#' @param virtualenv
#' Either the name of, or the path to, a Python virtual environment.
#'
#' @param condaenv
#' The conda environment to use. For `use_condaenv()`, this can be the name,
#' the absolute prefix path, or the absolute path to the python binary. If
#' the name is ambiguous, the first environment is used and a warning is
#' issued. For `use_miniconda()`, the only conda installation searched is
#' the one installed by `install_miniconda()`.
#'
#' @param conda
#' The path to a `conda` executable. By default, `reticulate` will check the
#' `PATH`, as well as other standard locations for Anaconda installations.
#'
#' @param required
#' Is the requested copy of Python required? If `TRUE`, an error will be
#' emitted if the requested copy of Python does not exist. If `FALSE`, the
#' request is taken as a hint only, and scanning for other versions will still
#' proceed. A value of `NULL` (the default), is equivalent to `TRUE`.
#'
#' @importFrom utils file_test
#'
#' @export
use_python <- function(python, required = NULL) {
required <- required %||% use_python_required()
if (required && !file_test("-f", python) && !file_test("-d", python))
stop("Specified version of python '", python, "' does not exist.")
# ensure that the python path is normalized as expected
python <- normalize_python_path(python)$path
# if required == TRUE and python is already initialized then confirm that we
# are using the correct version
if (required && is_python_initialized()) {
if (!file_same(py_config()$python, python)) {
fmt <- paste(
"ERROR: The requested version of Python ('%s') cannot be used, as",
"another version of Python ('%s') has already been initialized.",
"Please restart the R session if you need to attach reticulate",
"to a different version of Python."
)
msg <- sprintf(fmt, python, py_config()$python)
writeLines(strwrap(msg), con = stderr())
stop("failed to initialize requested version of Python")
}
}
# validate that this copy of python has libpython available
if (required) {
config <- python_config(python)
if (is.null(config$libpython)) {
fmt <- heredoc("
'%s' was not built with a shared library.
reticulate can only bind to copies of Python built with '--enable-shared'.
")
stopf(fmt, python)
}
}
if (required) {
# warn if we're overriding a previous request that will be ignored.
prior_required_python <- .globals$required_python_version
if (!is.null(prior_required_python) &&
!isTRUE(canonical_path(prior_required_python) == canonical_path(python)))
warningf(paste(
'Previous request to `use_python("%s", required = TRUE)` will be ignored.',
'It is superseded by request to `use_python("%s")'),
prior_required_python, python)
.globals$required_python_version <- python
# warn if this setting will be ignored because RETICULATE_PYTHON is set
python_w_precedence <- Sys.getenv("RETICULATE_PYTHON", NA)
if (!is.na(python_w_precedence) &&
!isTRUE(canonical_path(python_w_precedence) == canonical_path(python)))
warningf(paste(
'The request to `use_python("%s")` will be ignored because the',
'environment variable RETICULATE_PYTHON is set to "%s"'),
python, python_w_precedence)
}
.globals$use_python_versions <- unique(c(.globals$use_python_versions, python))
}
#' @rdname use_python
#' @export
use_python_version <- function(version, required = NULL) {
required <- required %||% use_python_required()
path <- pyenv_python(version)
use_python(path, required = required)
}
#' @rdname use_python
#' @export
use_virtualenv <- function(virtualenv = NULL, required = NULL) {
required <- required %||% use_python_required()
# resolve path to virtualenv
virtualenv <- virtualenv_path(virtualenv)
# validate it if required
if (required && !is_virtualenv(virtualenv))
stop("Directory ", virtualenv, " is not a Python virtualenv")
# get path to Python binary
suffix <- if (is_windows()) "Scripts/python.exe" else "bin/python"
python <- file.path(virtualenv, suffix)
use_python(python, required = required)
}
#' @rdname use_python
#' @export
use_condaenv <- function(condaenv = NULL, conda = "auto", required = NULL) {
required <- required %||% use_python_required()
if (grepl("[/\\]", condaenv) &&
grepl("^python[0-9.]*(exe)?", basename(condaenv))) {
# path to python binary provided
python <- condaenv
if (!is_conda_python(python))
warning("path supplied to use_condaenv() is not a conda python:\n\t",
python)
use_python(python, required = required)
return(invisible(NULL))
}
# check for condaenv supplied by path
condaenv <- condaenv_resolve(condaenv)
if (grepl("[/\\]", condaenv) && is_condaenv(condaenv)) {
python <- conda_python(condaenv)
use_python(python, required = required)
return(invisible(NULL))
}
# if the user has requested the 'base' environment, then just activate
# the conda installation associated with the conda binary found
#
# TODO: what if there are multiple conda installations? users could still
# use 'use_python()' explicitly to target a specific install
conda <- tryCatch(conda_binary(conda), error = identity)
if (inherits(conda, "error")) {
if (required)
stop(conda)
else
return(invisible(NULL))
}
if (identical(condaenv, "base")) {
bin <- dirname(conda)
suffix <- if (is_windows()) "../python.exe" else "python"
python <- file.path(bin, suffix)
return(use_python(python, required = required))
}
# list all conda environments
conda_envs <- conda_list(conda)
# look for one with that name
matches <- which(conda_envs$name == condaenv)
# if we had no matches, then either fail or return early as appropriate
if (length(matches) == 0) {
if (required)
stop("Unable to locate conda environment '", condaenv, "'.")
return(invisible(NULL))
}
# check for multiple matches (this could happen if the user has multiple
# Conda installations, or multiple environment paths)
envs <- conda_envs[matches, ]
if (nrow(envs) > 1) {
output <- paste(capture.output(print(envs)), collapse = "\n")
warning("multiple Conda environments found; the first-listed will be chosen.\n", output)
}
# we now have a copy of Python to use -- add it to the list
python <- envs$python[[1]]
use_python(python, required = required)
invisible(NULL)
}
#' @rdname use_python
#' @export
use_miniconda <- function(condaenv = NULL, required = NULL) {
required <- required %||% use_python_required()
# check that Miniconda is installed
if (!miniconda_exists()) {
msg <- paste(
"Miniconda is not installed.",
"Use reticulate::install_miniconda() to install Miniconda.",
sep = "\n"
)
stop(msg)
}
# use it
use_condaenv(
condaenv = condaenv,
conda = miniconda_conda(),
required = required
)
}
use_python_required <- function() {
# for now, assume that calls from within a package's .onLoad() are
# advisory, but we may consider relaxing this in the future
calls <- sys.calls()
for (call in calls) {
match <-
length(call) >= 2 &&
identical(call[[1L]], as.name("runHook")) &&
identical(call[[2L]], ".onLoad")
if (match)
return(FALSE)
}
# default to TRUE
TRUE
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.