class Solver: """ A high-level API to conda's solving logic. Three public methods are provided to access a solution in various forms. * solve_final_state * solve_for_diff * solve_for_transaction """ def __init__( self, prefix, channels, subdirs=(), specs_to_add=(), specs_to_remove=() ): """ Args: prefix (str): The conda prefix / environment location channels (Sequence[Channel]): A prioritized list of channels subdirs (Sequence[str]): A prioritized list of subdirs specs_to_add (set[MatchSpec]): Package specs to add specs_to_remove (set[MatchSpec]): Package specs to remove """
solve_final_state
solve_for_diff
solve_for_transaction
Returns the final, solved state of the environment.
from conda.api import Solverfrom conda.models.channel import Channelsolver = Solver( prefix="/path/to/env", channels=[Channel("conda-forge"), Channel("defaults")], specs_to_add=["numpy", "pandas"],)# Get the solved package listfinal_state = solver.solve_final_state()# final_state is a tuple of PackageRef in dependency orderfor package in final_state: print(f"{package.name} {package.version}")
Returns packages to remove and packages to add.
from conda.api import Solversolver = Solver( prefix="/path/to/env", channels=[Channel("conda-forge")], specs_to_add=["scipy==1.11"],)# Get the diffto_remove, to_add = solver.solve_for_diff()print(f"Removing {len(to_remove)} packages")print(f"Adding {len(to_add)} packages")
Returns an UnlinkLinkTransaction that can execute the solution.
from conda.api import Solversolver = Solver( prefix="/path/to/env", channels=[Channel("defaults")], specs_to_add=["python=3.11"],)# Get the transactiontransaction = solver.solve_for_transaction()# Execute the transactiontransaction.execute()
DepsModifier = _DepsModifier"""Flags to enable alternate handling of dependencies."""UpdateModifier = _UpdateModifier"""Flags to enable alternate handling for updates of existing packages."""
DepsModifier Options
Control how dependencies are handled:
NO_DEPS: Don’t install dependencies
ONLY_DEPS: Only install dependencies, not the package itself
UPDATE_DEPS: Update all dependencies to latest versions
UPDATE_DEPS_ONLY_DEPS: Update dependencies but not the main package
FREEZE_INSTALLED: Don’t update any installed packages
class SubdirData: """ High-level management and usage of repodata.json for subdirs. """ def __init__(self, channel): """ Args: channel (str or Channel): The target subdir """
from conda.api import SubdirDatafrom conda.models.channel import Channel# Initialize for a specific channel and platformsubdir = SubdirData(Channel("conda-forge/linux-64"))# Query for packages matching a specpackages = subdir.query("numpy>=1.20")for pkg in packages: print(f"{pkg.name} {pkg.version}")
class PackageCacheData: """ High-level management and usage of package caches. """ def __init__(self, pkgs_dir): """ Args: pkgs_dir (str): Path to the package cache directory """
Query Cache
Query All Caches
Find Writable Cache
from conda.api import PackageCacheDatacache = PackageCacheData("/path/to/pkgs")# Query for packages in cachecached_packages = cache.query("numpy")for pkg in cached_packages: print(f"{pkg.name} {pkg.version} - {pkg.package_tarball_full_path}")
from conda.api import PackageCacheData# Query all configured package cachespackages = PackageCacheData.query_all("scipy>=1.0")print(f"Found in cache: {len(packages)} packages")
from conda.api import PackageCacheData# Get the first writable package cachewritable_cache = PackageCacheData.first_writable()print(f"Writable cache: {writable_cache._internal.pkgs_dir}")print(f"Is writable: {writable_cache.is_writable}")
class PrefixData: """ High-level management and usage of conda environment prefixes. """ def __init__(self, prefix_path): """ Args: prefix_path (str): Path to the conda environment """
from conda.api import PrefixData# Get information about an environmentprefix = PrefixData("/path/to/env")# Iterate over installed packagesfor record in prefix.iter_records(): print(f"{record.name} {record.version}")
Here’s a complete example that creates an environment programmatically:
from conda.api import Solverfrom conda.models.channel import Channelfrom conda.base.context import contextimport osdef create_environment(env_path, packages, channels=None): """ Create a new conda environment programmatically. Args: env_path: Path where the environment will be created packages: List of package specs (e.g., ["python=3.11", "numpy"]) channels: List of channel names (defaults to context.channels) """ # Use default channels if none specified if channels is None: channels = context.channels # Convert channel names to Channel objects channel_objs = [Channel(c) for c in channels] # Create solver solver = Solver( prefix=env_path, channels=channel_objs, subdirs=context.subdirs, specs_to_add=packages, ) # Solve and create transaction print(f"Solving environment for {len(packages)} packages...") transaction = solver.solve_for_transaction() # Display what will be installed print(f"\nWill install {len(transaction.link_precs)} packages:") for pkg in transaction.link_precs[:5]: # Show first 5 print(f" - {pkg.name} {pkg.version}") if len(transaction.link_precs) > 5: print(f" ... and {len(transaction.link_precs) - 5} more") # Execute the transaction print("\nExecuting transaction...") transaction.execute() print(f"\nEnvironment created at: {env_path}")# Example usageif __name__ == "__main__": env_path = os.path.expanduser("~/my-conda-env") packages = ["python=3.11", "numpy", "pandas", "matplotlib"] channels = ["conda-forge", "defaults"] create_environment(env_path, packages, channels)