R/copernicus_python.R

Defines functions copernicus_import_module copernicus_install_package copernicus_configure_python

Documented in copernicus_configure_python copernicus_import_module copernicus_install_package

#' Search and initialize Python on any operating system (internal use)
#'
#' Searches for the Python executable in common paths and the system PATH.
#' If found, it initializes it via reticulate.
#'
#' @return The detected Python configuration (py_config object).
#' @importFrom reticulate use_python py_discover_config py_config import py_install
#' @importFrom utils install.packages
#' @importFrom stats na.omit
#' @keywords internal
copernicus_configure_python <- function(verbose = TRUE) {
  if (!requireNamespace("reticulate", quietly = TRUE)) {
    stop("The 'reticulate' package is required. Install it with install.packages('reticulate')")
  }

  sysname <- Sys.info()[["sysname"]]
  python_paths <- character()

  if (sysname == "Windows") {
    python_paths <- suppressWarnings(system("where python", intern = TRUE, ignore.stderr = TRUE))
  } else {
    python_paths <- suppressWarnings(system("which python3", intern = TRUE, ignore.stderr = TRUE))
    python_paths <- c(python_paths, suppressWarnings(system("which python", intern = TRUE, ignore.stderr = TRUE)))
  }

  # Paths comunes que agregas manualmente
  python_paths <- c(python_paths,
                    "C:/Python311/python.exe", "C:/Python312/python.exe", 
                    "C:/Python310/python.exe", "C:/Python39/python.exe", "C:/Python38/python.exe",
                    "/usr/local/bin/python3", "/usr/bin/python3", "/opt/python/bin/python3")

  python_paths <- unique(stats::na.omit(python_paths))
  python_found <- NULL

  for (path in python_paths) {
    if (file.exists(path) && !grepl("WindowsApps", path, ignore.case = TRUE)) {
      tryCatch({
        version_output <- system2(path, args = "--version", stdout = TRUE, stderr = TRUE)
        # Chequea versión mínima 3.7 usando expresión regular más amplia
        if (any(grepl("^Python 3\\.(7|8|9|1[0-9])", version_output))) {
          python_found <- path
          break
        }
      }, error = function(e) {})
    }
  }

  tryCatch({
    if (!is.null(python_found)) {
      reticulate::use_python(python_found, required = TRUE)
      if (verbose) message("Using Python at: ", python_found)
    } else {
      if (verbose) message("Searching for Python automatically with reticulate...")
      pyconf <- reticulate::py_discover_config()
      viable_pythons <- pyconf$python_versions[!grepl("WindowsApps", pyconf$python_versions, ignore.case = TRUE)]
      if (length(viable_pythons) > 0) {
        reticulate::use_python(viable_pythons[1], required = TRUE)
        if (verbose) message("Automatically detected Python: ", viable_pythons[1])
      } else {
        stop("No suitable Python (>=3.7) installation found. Please install from https://www.python.org/downloads/")
      }
    }

    config <- reticulate::py_config()
    if (verbose) message("Python version: ", config$version_string)
    return(config)

  }, error = function(e) {
    stop("Python configuration failed. ", e$message)
  })
}


#' Install the Python package copernicusmarine (internal use)
#'
#' @param py Python configuration object.
#' @param verbose Show detailed messages.
#' @return Invisible TRUE if the installation is successful.
#' @importFrom reticulate py_install
#' @keywords internal
copernicus_install_package <- function(py = NULL, verbose = TRUE) {
  if (!requireNamespace("reticulate", quietly = TRUE)) {
    stop("The 'reticulate' package is required.")
  }

  tryCatch({
    if (is.null(py)) {
      reticulate::py_install("copernicusmarine", pip = TRUE, verbose = verbose)
    } else {
      reticulate::py_install("copernicusmarine", envname = py$python, pip = TRUE, verbose = verbose)
    }
    if (verbose) message("copernicusmarine installed successfully.")
  }, error = function(e) {
    message("Error installing copernicusmarine via reticulate::py_install(): ", e$message)
    message("Try installing it manually in your system or Python environment:")
    message("Run in a terminal: pip install copernicusmarine")
  })

  invisible(TRUE)
}


#' Import the copernicusmarine Python module (internal use)
#'
#' @param py Python configuration object.
#' @return Imported copernicusmarine module.
#' @importFrom reticulate import
#' @keywords internal
copernicus_import_module <- function(py) {
  tryCatch({
    reticulate::import("copernicusmarine")
  }, error = function(e) {
    stop("Could not import copernicusmarine. Run: copernicus_reinstall_package()")
  })
}

Try the copernicusR package in your browser

Any scripts or data that you put into this service are public.

copernicusR documentation built on Aug. 8, 2025, 7:06 p.m.