Package Management#
Learning Objectives#
Understand the basics of Julia’s package management system
Add (install), remove, and update packages using Julia’s package manager
View and manage installed packages (e.g. check the status of the environment)
Import and use installed packages in your Julia code
Identify some common Julia packages and their uses and understand best practices for package management
Overview of Julia’s Package System#
Julia’s package ecosystem provides a wide range of functionality, from data manipulation and plotting to machine learning and beyond. Julia ships with a package manager called Pkg
that is designed to make it easy to install and manage these packages and their dependencies.
Pkg
uses a concept called environments:
An environment is basically a set of packages and specific versions that you have downloaded to use.
By default, when you use the Julia REPL or Jupyter, you’re in the “default environment”.
However, you can create separate environments for each project you work on, so that you only work with the packages (and versions) needed for that project. The details of the packages and versions are recorded in files
Project.toml
andManifest.toml
that reside in your project folder.It is highly recommended that you use a separate environment for each project you work on, as this greatly enhances the reproducibility of your work.
For the most part, it is best not to install packages into the default environment (apart perhaps from a few select language or development tools, such as
IJulia
for using Julia in Jupyter notebooks).
Why use project-specific environments?
When you install packages into the default environment, you risk version conflicts between projects, as different projects may require different versions of the same package. This can lead to compatibility issues and unexpected behavior. Additionally, installing everything into the default environment makes it harder to track which packages are needed for which projects. Project-specific environments isolate dependencies, ensuring that each project has its own set of packages, which helps in avoiding these problems and makes your development process more reliable and reproducible.
The Project.toml
and Manifest.toml
files#
The Project.toml
and Manifest.toml
files enable Julia to manage and precisely specify environments.
The
Project.toml
file describes the project’s requirements at a high level. It plays an important role when developing Julia packages (which we won’t cover in this course), where it is also used to include package metadata e.g. authors, version, package compatability constraints etc. For our purposes,Project.toml
just lists out the direct package dependencies for our project.The
Manifest.toml
file records the precise state of the environment at a given time, giving a detailed snapshot of the exact versions of all packages within an environment, including their transitive dependencies. It allows us to instantiate an environment with exactly the same packages and versions that somebody else used to run their code.
Importantly, in order for someone else to run our code using the same packages and versions that we used, we just need to give them Project.toml
and Manifest.toml
along with our code.
Using the Pkg
REPL#
The easiest way to use Pkg
is through a dedicated REPL built into the Julia REPL. To access it, open the Julia REPL and then enter the ‘command’ ]
:
julia> ]
(v1.11) pkg>
You can see that the prompt changes. The REPL opens in the default environment, indicated by the Julia version number (v1.11
in the above example). There is also the dedicated pkg>
prompt to indicate we’re in the Pkg
REPL, rather than Julia’s normal REPL.
To exit back to the regular Julia REPL, just hit backspace from within the Pkg
REPL.
To see help text for using the Pkg
REPL, use the help
command:
(v1.11) pkg> help
Creating / activating an environment#
Creating a Pkg
environment is simply a matter of:
Choosing a folder on our file system to associated with the environment. Typically this will be the folder where you are writing your code for some project / application. This is where the associated
Project.toml
andManifest.toml
files will reside.Using the
Pkg
REPL to activate the environment (creating theProject.toml
andManifest.toml
files if necessary.
Let’s suppose we have a folder MyProject
where we are writing (or will write) our code. To activate an evironment within MyProject
we enter the Pkg
REPL and then call activate
with the path to the MyProject
folder (with respect to the directory where we started the Julia REPL):
julia> ]
(v1.11) pkg> activate path/to/MyProject
Activating new project at `path/to/MyProject`
(MyProject) pkg>
Notice how the prompt now indicates we’re working with the environment MyProject
.
Note: activating a new project will not yet create Project.toml
and Manifest.toml
- these will be created once we start adding packages.
Adding and removing packages#
To add a package to an environment to make it available to use in our code, use the add
command from within the Pkg
REPL. E.g. to add the latest version of the Plots.jl
package to our environment:
(MyProject) pkg> add Plots
Note that we don’t include the .jl
suffix!
Julia will download the package if required and then add it to the environment. It will also create / update the Project.toml
and Manifest.toml
files.
If we need to install a specific version, we just specify it with an @
prefix:
(MyProject) pkg> add Plots@1.40.2
To remove a package from the environment, just use the remove
(or rm
) command:
(MyProject) pkg> remove Plots
Note
Julia stores packages in a central ‘depot’ that is shared across environments, to optimise package management and reduce redundant downloads. When you
add
a package, Julia first checks this depot to see if the package (at the specific / latest version) is already available. If the package is found, it is used directly, speeding up the installation process. If the package is not found, Julia downloads it from the internet and stores it in the depot for future use. However, only the packages explicitlyadd
ed to an environment are available for use within that environment.
Listing packages in the environment#
To list the packages within the environment that are direct requirements for the project (i.e. specified in Project.toml
), use the status
(or st
) command:
(MyProject) pkg> status
Status `path/to/MyProject/Project.toml`
[91a5bcdd] Plots v1.40.13
To list all packages in the environment (as detailed in the Manifest.toml
), use the --manifest
option:
(MyProject) pkg> status --manifest
Status `path/to/MyProject/Manifest.toml`
[66dad0bd] AliasTables v1.1.3
[d1d4a3ce] BitFlags v0.1.9
[944b1d66] CodecZlib v0.7.8
[35d6a980] ColorSchemes v3.29.0
[3da002f7] ColorTypes v0.12.1
[c3611d14] ColorVectorSpace v0.11.0
...
[91a5bcdd] Plots v1.40.13
...
[-- full output suppressed --]
Updating packages#
All packages#
To update all packages within the environment (i.e. all those specified in Manifest.toml
), use the update
(or up
) command:
(MyProject) pkg> update
Julia will ensure that any version restrictions enforced by dependent packages are maintained.
Specific packages#
To update a specific package, use update
with the name of the package:
(MyProject) pkg> update Plots
Again, Julia will ensure that any version restrictions enforced by dependent packages are maintained.
By default, if you specify a package Julia will only update that package, not any other packages that it may depend upon. To allow Julia to update all dependent packages as well, supply the --preserve=none
option:
(MyProject) pkg> update --preserve=none Plots
Note that update
is only used to install later versions. To replace a package with an older version, use add
and specify the package with the version you want.
Instantiating an environment from Project.toml
and Manifest.toml
#
Given a folder NewProject
where we already have Project.toml
and Manifest.toml
files, we can add all the packages specified in these files using the instantiate
command. Note that we need to ensure we activate the project first:
(v1.11) pkg> activate path/to/NewProject
(NewProject) pkg> instantiate
Exercise: an environment with Plots
#
Create a new environment and add the
Plots
package to it.List all packages in environment (try with and without the
--manifest
option).Take a peek at the
Project.toml
andManifest.toml
to see the difference between these files (but don’t modify them!)
Best practices with packages#
Don’t modify
Manifest.toml
by hand! Doing so could break Julia’s package management capabilities for your project.When sharing your work with others, make sure to send them the
Project.toml
andManifest.toml
files so that they can reproduce your environment.Keep the
Project.toml
andManifest.toml
files under version control, to track package updates.If using the
Pkg
API in your code, don’t usePkg.add
in performance-critical code or inside functions that run repeatedly.Use
using
orimport
statements at the top of your script/notebook, to make clear what external libraries your code is using.
Julia’s Standard Library#
Julia contains a standard library of modules. These are basically just packages that ship with Julia and are ready in any environment (you don’t need to add
them). There are many useful modules, here are just a small selection:
Pkg
: for doing package management using Julia code e.g.Pkg.activate("MyProject")
,Pkg.add("Plots")
etc.Dates
: for working with dates and timestampsTest
: for unit testingDelimitedFiles
: for working with delimited files e.g. CSV.LinearAlgebra
: for linear algebra computationsLogging
: for logging
See the Julia docs for more information.
Using packages in your code#
Every package defines a module of the same name (e.g. the Plots.jl
pakcage defines the module Plots
). Modules are Julia’s way of namespacing. To use the functionality of a package in your Julia code, you have two primary options: via using
and import
. They differ in how they bring names from the module into your namespace:
using PackageName
: This brings all exported names from thePackageName
module directly into your current scope, as well asPackageName
itself. You can call those names without qualifying them by the module name. (You can still use the module to qualify the names if you like e.g.PackageName.do_something()
import PackageName
: This makes the modulePackageName
available, but does not pull any of its names into your scope. You must qualify everything with the module’s name.
For example, If you wanted to use the Julia standard library Dates
module, the two approaches would be:
# Import Dates and call `today` function
import Dates
Dates.today()
2025-06-07
# Using Dates and call `today` function
using Dates
today() # or Dates.today()
2025-06-07
Exercise: using Plots
#
The plot
function from the Plots.jl
can be used to plot a line graph:
# TODO: what to write here to make the plotting code work?
# Plot y = x^3
x = range(-1, 1; step=0.01)
y = x .^ 3
Plots.plot(x, y)
Complete the code above so that it runs. How could you modify the code so that we call plot
instead of Plots.plot
?
Overview of Common 3rd party Packages in Julia#
Julia has a rich ecosystem of packages that cater to various needs such as data manipulation, visualisation, scientific computing, and more. Below is an overview of some commonly used packages along with links to detailed resources for each package.
StaticArrays.jl#
StaticArrays.jl
provides stack-allocated, fixed-size arrays optimised for ultra-fast small-matrix and vector computations.
DifferentialEquations.jl#
DifferentialEquations.jl
provides a unified framework providing best-in-class, high-performance solvers for ODEs, SDEs, DAEs, and PDEs.
DataFrames.jl#
DataFrames.jl
provides tools for working with tabular data, similar to pandas in Python or data.frame in R. It is essential for data manipulation and analysis.
Plots.jl#
Plots.jl
is a powerful and flexible plotting package in Julia. It supports multiple backends and is widely used for creating a variety of visualisations.
CSV.jl#
CSV.jl
is a fast and reliable package for reading and writing CSV files. It integrates seamlessly with DataFrames.jl
for handling tabular data.
JuMP.jl#
JuMP.jl
is a domain-specific modelling language for mathematical optimisation embedded in Julia.
It is used for linear programming, non-linear programming, and other optimisation problems.
Distributions.jl#
Distributions.jl
provides a large collection of probability distributions and related functions. It is useful for statistical modelling and probabilistic computations.
Flux.jl#
Flux.jl
is a machine learning library in Julia. It is designed to be easy to use while being highly extensible, providing tools for building and training neural networks.
Makie.jl#
Makie.jl
is a high-performance plotting library for data visualisation. It provides a powerful and flexible interface for creating complex visualisations.
HTTP.jl#
HTTP.jl
is a package for handling HTTP requests and responses. It is useful for web development, API interactions, and network programming.
Gadfly.jl#
Gadfly.jl
is a plotting and data visualisation system inspired by ggplot2 in R. It is great for creating complex, aesthetically pleasing plots.
By using the above links, you can explore more about each package and learn how to effectively use them in Julia.
Exercise: Exploring Julia Packages#
Julia has a rich ecosystem of packages that support a wide range of tasks. Now it’s your turn to explore one of these packages and see how it might fit into your own workflows or projects.
Choose one package from the list above that aligns with your interests or the kind of work you expect to do after this course (e.g. data analysis, visualisation, optimisation, scientific computing, etc.).
Create an environment and install the package into it.
Try a simple example using the package:
For plotting packages, create a basic plot (e.g. line plot, scatter plot).
For data packages, load or create a small dataset and perform a basic manipulation or analysis.