4. 使用“环境”

下面讨论 Pkg 与环境的交互。有关环境在代码加载中扮演的角色的更多信息,包括可以从中加载代码的环境的“栈”,请参阅Julia 手册中的此部分

创建自己的环境

到目前为止,我们已经将包添加到默认环境中 ~/.julia/environments/v1.8。然而,创建另外的独立项目很容易。这种方法的好处是允许您在代码旁边创建 Project.tomlManifest.toml 文件,并添加进版本控制(例如 git)中。需要指出的是,当两个项目使用相同版本的同一个包时,这个包的内容只保存一份。为新项目创建一个目录,然后激活该目录以使其成为“活动项目”,操作如下:

(@v1.8) pkg> activate MyProject
Activating new environment at `~/MyProject/Project.toml`

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

请注意,激活新项目时,REPL 提示会发生变化。在添加包之前,此环境中没有文件,甚至可能不会创建环境目录:

julia> isdir("MyProject")
false

(MyProject) pkg> add Example
   Resolving package versions...
   Installed Example ─ v0.5.3
    Updating `~/MyProject/Project.toml`
  [7876af07] + Example v0.5.3
    Updating `~~/MyProject/Manifest.toml`
  [7876af07] + Example v0.5.3
Precompiling environment...
  1 dependency successfully precompiled in 2 seconds

julia> readdir("MyProject")
2-element Vector{String}:
 "Manifest.toml"
 "Project.toml"

julia> print(read(joinpath("MyProject", "Project.toml"), String))
[deps]
Example = "7876af07-990d-54b4-ab0e-23690620f79a"

julia> print(read(joinpath("MyProject", "Manifest.toml"), String))
# This file is machine-generated - editing it directly is not advised

julia_version = "1.8.2"
manifest_format = "2.0"
project_hash = "2ca1c6c58cb30e79e021fb54e5626c96d05d5fdc"

[[deps.Example]]
git-tree-sha1 = "46e44e869b4d90b96bd8ed1fdcf32244fddfb6cc"
uuid = "7876af07-990d-54b4-ab0e-23690620f79a"
version = "0.5.3"

新环境与我们之前使用的环境完全不同。有关更详细的说明,请参阅 Project.tomlManifest.toml

使用别人的项目

只需使用 git clone 克隆别人的项目, 然后 cd 到项目目录并调用:

shell> git clone https://github.com/JuliaLang/Example.jl.git
Cloning into 'Example.jl'...
...

(@v1.8) pkg> activate Example.jl
Activating project at `~/Example.jl`

(Example) pkg> instantiate
  No Changes to `~/Example.jl/Project.toml`
  No Changes to `~/Example.jl/Manifest.toml`

如果项目包含 manifest,这将以该 manifest 给出的相同状态安装包。否则,它将解析与项目兼容的最新版本的依赖项。

请注意,activate 本身不会安装缺少的依赖项。如果您只有一个 Project.toml 文件, 则 Manifest.toml 必须通过“解析”环境来生成,任何丢失的包都必须安装并预编译。instantiate 命令为你做了这些工作。

如果您已经有一个已解析的 Manifest.toml,那您仍然需要确保所有软件包及其正确版本都已安装。 instantiate 再次为您执行这些操作。

简而言之,instantiate 确保环境已经准备好可以使用。如果什么也不用做,那么 instantiate 什么也不做。

Note

您可以使用 --project=<path> 参数在启动时指定项目,替代在 Julia 中使用 activate。例如,要使用当前目录中的环境从命令行运行脚本,您可以运行

$ julia --project=. myscript.jl

临时环境

临时环境可以轻松地从空白环境开始以测试一个包或一组包,并让 Pkg 在您测试完后自动删除环境。例如,在编写错误报告时,您可能希望在一个“干净”环境中测试您的最小复现示例,以保证它确实是可复现的。您可能还需要一个临时空间来试用一个新包,或者一个沙箱来解决几个不兼容的包之间的版本冲突。

(@v1.8) pkg> activate --temp # requires Julia 1.5 or later
  Activating new environment at `/var/folders/34/km3mmt5930gc4pzq1d08jvjw0000gn/T/jl_a31egx/Project.toml`

(jl_a31egx) pkg> add Example
    Updating registry at `~/.julia/registries/General`
   Resolving package versions...
    Updating `/private/var/folders/34/km3mmt5930gc4pzq1d08jvjw0000gn/T/jl_a31egx/Project.toml`
  [7876af07] + Example v0.5.3
    Updating `/private/var/folders/34/km3mmt5930gc4pzq1d08jvjw0000gn/T/jl_a31egx/Manifest.toml`
  [7876af07] + Example v0.5.3

共享环境

“共享”环境是存在于 ~/.julia/environments 的简单环境,因此,默认的 v1.8 环境是共享环境:

(@v1.8) pkg> st
Status `~/.julia/environments/v1.8/Project.toml`

可以使用 activate 命令的 --shared 参数激活共享环境 :

(@v1.8) pkg> activate --shared mysharedenv
  Activating project at `~/.julia/environments/mysharedenv`

(@mysharedenv) pkg>

共享环境在 Pkg REPL 提示符中的名称前有一个 @

环境预编译

在导入包之前,Julia 会将源代码“预编译”到磁盘上更高效的中间缓存中。如果未导入的包是新的或自上次缓存以来已发生更改,则可以通过“代码加载”触发此预编译。

julia> using Example
[ Info: Precompiling Example [7876af07-990d-54b4-ab0e-23690620f79a]

或者使用 Pkg 的预编译选项,它可以并行预编译整个环境或给定的依赖项,这比上面的代码加载方式快得多。

(@v1.8) pkg> precompile
Precompiling environment...
  23 dependencies successfully precompiled in 36 seconds

然而,由于 Pkg 的自动预编译机制,以上两种方式通常是不需要的。

自动预编译

默认情况下,任何添加到项目或在 Pkg 操作中更新的包以及它的依赖项都将自动预编译。

(@v1.8) pkg> add Images
   Resolving package versions...
    Updating `~/.julia/environments/v1.9/Project.toml`
  [916415d5] + Images v0.25.2
    Updating `~/.julia/environments/v1.9/Manifest.toml`
    ...
Precompiling environment...
  Progress [===================>                     ]  45/97
  ✓ NaNMath
  ✓ IntervalSets
  ◐ CoordinateTransformations
  ◑ ArnoldiMethod
  ◑ IntegralArrays
  ◒ RegionTrees
  ◐ ChangesOfVariables
  ◓ PaddedViews

develop 命令是个例外,它既不构建也不预编译包。何时预编译由用户决定。

如果在自动预编译期间给定的包版本出错,Pkg 会记住它,下面的自动尝试都会跳过该包并发出简短的警告。手动预编译可用于强制重试这些包,因为 pkg> precompile 将始终重试所有包。

要禁用自动预编译,请设置 ENV["JULIA_PKG_PRECOMPILE_AUTO"]=0.

预编译已加载包的新版本

如果会话中已经加载了已更新的包,则预编译过程将继续并预编译新版本以及任何依赖它的包,但需注意该包在会话重新启动之前无法使用。