avatarGwang Jin Kim, PhD

Summary

This article explains how to use Julia's Package Manager to install, manage, and update packages in the Julia programming language.

Abstract

The article begins by explaining how to enter and exit the Package Manager environment from the REPL (Read-Eval-Print Loop) in Julia. It then provides instructions on how to install a Julia package, either from the Julia REPL or the Package Manager. The article also explains the difference between using the import and using keywords when importing packages in Julia. The article then covers how to remove, update, and list installed packages using the Package Manager. Finally, the article explains how the Package System manages virtual environments in Julia.

Opinions

  • The author believes that using the import keyword is more appropriate for clean scripts, where the package name is explicitly mentioned, while using the using keyword is more suitable for hacking in the REPL, where typing less is preferred.
  • The author suggests that the Package System in Julia is useful for managing virtual environments, as it allows for precise control over which packages are visible or not.
  • The author recommends using the activate command to switch between virtual environments in Julia.
  • The author notes that the Package Manager environment can see all packages installed in the global environment, but packages added to a specific virtual environment will not be visible in the global environment.
  • The author provides a helpful tip for resolving package version conflicts by using the compat command in the Package Manager.

Exploring Julia’s Package Manager

Learn Julia With Me!

Photo by Petrebels on Unsplash

In this article, I want to go through Julia’s Package Manager documentation with you and summarize what I read.

Entering And Exiting The Package Manager From The REPL

You enter the Package Manager environment by pressing] .

# the prompt changes then to:
(@v1.9) pkg>

You get back to the Julia REPL by BACKSPACE or C-c (Ctrl-c).

# you are then back to the Julia REPL:
julia>

Install A Julia Package

You can install a Julia package both from the Julia REPL or the Package Manager.

# Install the Package `Example` from the Julia REPL:
julia> using Pkg
julia> Pkg.add("Example")
# after successful installation, you have to `import` it or use `using`
julia> using Example # or also: `import Example`
# then use call a function from Example
julia> Example.hello("friend")
"Hello, friend"

But you can from the Julia REPL also go first to the package manager environment and then run there the command and come back to Julia REPL:

julia> # press to enter the package manager by pressing `]`
pkg> add Example
# after successful installation, go back to the REPL by `BACKSPACE` or `C-c`
julia> import Example
julia> Example.hello("friend")
"Hello, friend"

You can install multiple packages with one command:

julia> using Pkg; Pkg.add("Example", "Plots")

# or:
pkg> add Example Plots

Back in the Julia REPL, you have to import the packages:

julia> import Example
julia> import Plots

# or:

julia> using Example
julia> using Plots

What Is The Difference Between import and using?

After import, you have to mention the package name always at the beginning. The package Examplehas explorted two functions/methods, hello and domath. Nevertheless, these are exported functions, you can call them only with the package name prefixed.

julia> import Example
julia> Example.hello("Bob")
"Hello, Bob"
julia> Example.domath(1)
6
julia> domath
ERROR: UndefVarError: `domath` not defined
julia> hello
ERROR: UndefVarError: `hello` not defined

However, after using Example , methods which were exported in the imported modules are exported to the current environment. So that you can call them directly without the prefix Example. :

julia> using Example
julia> hello("Bob")
"Hello, Bob"
julia> domath(1)
6
julia> Example.hello("Bob")
"Hello, Bob"
julia> Example.domath(1)
6

So maybe import is more for clean Scripts, where you want to explicitely mention where (which Package) you have a function or object from.

And using is more for hacking in the REPL, where you want to type less.

You can however, explicitely import single functions or Objects in Julia:

julia> import Example.hello
# after that, you can do:
julia> hello("Bob")
"Hello, Bob"

It just requires more typing from your site.

You Have To Import A Function/Method, When You Want to Extend It!

We had this example already back in

If we define our own Type or Struct, and if we want an existing method in another package (e.g. the Base package) dispatch also for this new Type or Struct, we need to extend the function/method.

This we can do only after importing the function/method from the package. But not after using the package:

struct Point
    x::Float64
    y::Float64
end

p1 = Point(1, 3)  ## Point(1.0, 3.0)
p2 = Point(5, 9)  ## Point(5.0, 9.0)

# the method `+` was added to the session through `using Base`
julia> function +(point1::Point, point2::Point)
           Point(point1.x + point2.x, point1.y + point2.y)
       end
ERROR: error in method definition: function Base.+ must be explicitly imported to be extended

# you get this error.
# you do it correctly by:

# first import-ing the method is necessary to be able to extend its dispatch
import Base.+

julia> function +(point1::Point, point2::Point)
           Point(point1.x + point2.x, point1.y + point2.y)
       end
+ (generic function with 208 methods)

# and now you can use the + operator for the points
p1 + p2       ## Point(6.0, 12.0)

Remove Packages by `rm` or `remove`

julia> Pkg.rm("Example")

pkg> rm Example    

As with add, you can list multiple packages for rm.

Update Packages by `up`

pkg> up

List All Packages Installed In the Current Environment by `st` or `status`

pkg> st

# or
pkg> status

Show All Available Commands In Pkg Environment

pkg> ?

# show help for single command
pkg> ?develop

The Package System Manages Also Virtual Environments

Acutally, if you enter your Package Manager environment via ] from your REPL, you see at the beginning (@v1.9) pkg> . The (@v1.9) means, that you are in a global virtual environment.

The status command st or status shows you where your virtual environment is located. Because every virtual environment is a folder with a Project.toml file (and eventually a corresponding Manifet.toml file).

(@v1.9) pkg> st
Status `~/.julia/environments/v1.9/Project.toml`
  [a93c6f00] DataFrames v1.6.1
  [c43c736e] Genie v5.18.2
  [14b8a8f1] PkgTemplates v0.7.44
  [91a5bcdd] Plots v1.39.0
  [295af30f] Revise v3.5.3

So this shows, that we are in the global environment v1.9 which has its Project.toml file located in the displayed path.

Wherever you are at the moment, you can anytime create a new project folder with a Project.toml file in it, which then applies only for the project folder, by doing:

julia> cd("path/to/new/folder") # in our case we are in the home folder
julia> pwd() # show current location
"/home/josephus"
# enter package environment by `]`
(@v1.9) pkg>
# now activate a new environment called `tutorial`
(@v1.9) pkg> activate tutorial
  Activating new project at `~/tutorial`

(tutorial) pkg> 
# so this create where you are at the moment a `tutorial` project folder
# and let's you enter this virtual environment as indicated by: (tutorial)
# at the beginning before `pkg>`,
# and generates automatically a `Project.toml` file into it which 
# however is emtpy as you can check by:
(tutorial) pkg> st
Status `~/tutorial/Project.toml` (empty project)

It seems, this environment can see all packages which were installed into the global (@v1.9) environment. However, if you enter the tutorial environment by activating it, and add there packages, and go back to (@v1.9) and then to the REPL, then suddengly you cannot “see” the packages which you added to the tutorial environment.

julia> # `]`
(@v1.9) pkg> st
Status `~/.julia/environments/v1.9/Project.toml`
  [a93c6f00] DataFrames v1.6.1
  [c43c736e] Genie v5.18.2
  [14b8a8f1] PkgTemplates v0.7.44
  [91a5bcdd] Plots v1.39.0
  [295af30f] Revise v3.5.3

# you see the currently enlisted packages - you will have different ones
# and then now switch to `tutorial` environemnt
(@v1.9) pkg> activate tutorial
  Activating project at `~/tutorial`

(tutorial) pkg> st
Status `~/tutorial/Project.toml` (empty project)

# now you install Example package into this environment

(tutorial) pkg> add Example
   Resolving package versions...
    Updating `~/tutorial/Project.toml`
  [7876af07] + Example v0.5.3
    Updating `~/tutorial/Manifest.toml`
  [7876af07] + Example v0.5.3
# then you go back to the REPL by BACKSPACE
julia>
# and now import Example
julia> using Example
julia> hello("Bob")
"Hello, Bob"

# now switch to package environment via `]`
(tutorial) pkg> st
Status `~/tutorial/Project.toml`
  [7876af07] Example v0.5.3

# now switch back to global
(tutorial) pkg> activate @v1.9

(@v1.9) pkg> st
Status `~/.julia/environments/v1.9/Project.toml`
  [a93c6f00] DataFrames v1.6.1
  [c43c736e] Genie v5.18.2
  [14b8a8f1] PkgTemplates v0.7.44
  [91a5bcdd] Plots v1.39.0
  [295af30f] Revise v3.5.3

# and switch back to REPL by BACKSPACE

julia> hello("Bob")
"Hello, Bob"

# the package and function are still loaded from previous loading
# but if you re-import the module, julia can't find the Example package
# any more:

julia> using Example
 │ Package Example not found, but a package named Example is available from a registry. 
 │ Install package?
 │   (@v1.9) pkg> add Example 
 └ (y/n/o) [y]: n
ERROR: ArgumentError: Package Example not found in current path, maybe you meant `import/using .Example`.
- Otherwise, run `import Pkg; Pkg.add("Example")` to install the Example package.
Stacktrace:
 [1] macro expansion
   @ ./loading.jl:1630 [inlined]
 [2] macro expansion
   @ ./lock.jl:267 [inlined]
 [3] require(into::Module, mod::Symbol)
   @ Base ./loading.jl:1611

julia>

So through activating into virtual environments, we can precisely control which packages are visible or not.

And as we see with the help:

(@v1.9) pkg> ?
  Welcome to the Pkg REPL-mode. To return to the julia> prompt, either press backspace when the input line is empty or
  press Ctrl+C.

  Full documentation available at https://pkgdocs.julialang.org/

  Synopsis

  pkg> cmd [opts] [args]

  Multiple commands can be given on the same line by interleaving a ; between the commands. Some commands have an
  alias, indicated below.

  Commands

  activate: set the primary environment the package manager manipulates

  add: add packages to project

  build: run the build script for packages

  compat: edit compat entries in the current Project and re-resolve

  develop, dev: clone the full package repo locally for development

  free: undoes a pin, develop, or stops tracking a repo

  gc: garbage collect packages not used for a significant time

  generate: generate files for a new project

  help, ?: show this message

  instantiate: downloads all the dependencies for the project

  pin: pins the version of packages

  precompile: precompile all the project dependencies

  redo: redo the latest change to the active project

  remove, rm: remove packages from project or manifest

  resolve: resolves to update the manifest from changes in dependencies of developed packages

  status, st: summarize contents of and changes to environment

  test: run tests for packages

  undo: undo the latest change to the active project

  update, up: update packages in manifest

  why: shows why a package is in the manifest

  registry add: add package registries

  registry remove, rm: remove package registries

  registry status, st: information about installed registries

  registry update, up: update package registries

There are many commands to control single packages within a virtual environment. Like pin-ning them, add-ing them, remove/rm-ing them,

generate new projects, build these projects,

instatiate- meaning installing all packages which are listed in the Project.toml file.

Each single of the commands, we can inspect with pkg> ?<commandname> in the package environment.

Julia
Julialang
Python
Packaging
DevOps
Recommended from ReadMedium
avatarCharles Verleyen
Airflow 2.10 is just wow

Introduction

8 min read