在命令行中启动Julia时,可以指定项目目录。其中一个选项是@.
,可能是当前目录。在这种情况下,@.
是什么?
# from `julia --help`
--project[={<dir>|@.}] Set <dir> as the home project/environment
来自docs:
如果变量设置为@。,Julia会尝试从当前目录及其父目录中查找包含Project.toml或JuliaProject.toml文件的项目目录。
我意识到cli --project
参数解析发生在这个C code中,并且显然被这个init code使用,虽然我不确定它们之间的事件顺序。
特别是在initdefs.jl我们有:
project = (JLOptions().project != C_NULL ?
unsafe_string(Base.JLOptions().project) :
get(ENV, "JULIA_PROJECT", nothing))
HOME_PROJECT[] =
project == nothing ? nothing :
project == "" ? nothing :
project == "@." ? current_project() : abspath(project)
我对这段代码的解读是@.
只是一个任意的标记,它可能是一个简单的.
为cli? Julia如何搜索“当前目录及其父项”。
LOAD_PATH
(["@", "@v#.#", "@stdlib"]
)中使用了类似的符号,正如here和here所讨论的那样。 @.
是否与LOAD_PATH
符号属于同一个扩展族?
--project
--project
标志定义了“家庭项目”或“家庭环境”。环境由Project.toml
/ Manifest.toml
定义,并定义哪个包可用于using
/ import
。
您可以将--project
设置为(i)目录(有或没有Project.toml
)(ii)通往Project.toml
的路径或(iii)@.
。 (i)和(ii)非常不言自明 - 朱莉娅将把该项目视为家庭项目。现在为(iii),如果你设置--project=@.
Julia将尝试找到现有的Project.toml
文件并将其用作主项目。请考虑以下示例:
~$ tree .
.
├── A
└── Project.toml
1 directory, 1 file
其中A
是一个空目录。我们可以轻松地尝试(i)和(ii):
# existing file
[~]$ julia --project=Project.toml -E 'Base.active_project()'
"~/Project.toml"
# existing directory
[~]$ julia --project=A -E 'Base.active_project()'
"~/A/Project.toml"
# non-existing directory
[~]$ julia --project=B -E 'Base.active_project()'
"~/B/Project.toml"
# non-existing file
[~]$ julia --project=B/Project.toml -E 'Base.active_project()'
"~/B/Project.toml"
请注意,在上面的三个最后一个示例中,Project.toml
文件不存在,但是如果需要它将被创建(例如,当使用Pkg
来操作包时)。
现在,将其与@.
的行为进行比较,# from our root directory
[~]$ julia --project=@. -E 'Base.active_project()'
"~/Project.toml"
# from inside the A directory
[~/A]$ julia --project=@. -E 'Base.active_project()'
"~/Project.toml"
将查找现有的项目文件:
Project.toml
在这两种情况下,我们发现了相同的@.
文件。使用Project.toml
选项,Julia首先在当前目录中查找Project.toml
文件,如果找不到,则将一个级别升级到父文件夹并查看,依此类推。这就是第二个例子中发生的事情; Julia没有在空的A
目录中找到Project.toml
文件,所以我们移动到父目录,找到了我们在那里的.
。
是的,我们可以选择其他一些令牌,但不是--project
,因为那已经有了意义;它是当前目录的路径,是与"@"
一起使用的完全有效的路径。
Example
要加载一个包Example
,我们在[deps]
部分用Base.load_path()
定义一个家庭项目是不够的;家庭项目还需要出现在Julias加载路径(["@", "@v#.#", "@stdlib"]
)中。默认情况下,加载路径从"@v#.#"
扩展,其中~/.julia/environments/v#.#
扩展为#
,"@stdlib"
替换为Julias主要版本号和次要版本号,"@"
扩展到带有Julias标准库的目录。 Pkg.activate
扩展为1.一个活跃的项目(用pkg> activate
/ Base.load_path()
激活)或2.家庭项目。我们可以使用# without home project; @ expands to nothing
[~]$ julia -E 'Base.load_path()'
["~/.julia/environments/v1.0/Project.toml", "~/julia10/usr/share/julia/stdlib/v1.0"]
# with home project; @ expands to our specified home project
[~]$ julia --project=@. -E 'Base.load_path()'
["~/Project.toml", "~/.julia/environments/v1.0/Project.toml", "~/julia10/usr/share/julia/stdlib/v1.0"]
检查扩展的加载路径:
"@"
最后,如果我们从加载路径中删除[~]$ export JULIA_LOAD_PATH="" && julia --project=@. -E 'Base.load_path()'
String[]
,我们定义一个home项目并不重要:
Base.load_path()
基于@fredrikekre的回答,写了一个脚本来探索Base.active_project()
,Base.current_project()
,"""
Explore Base.load_path() behaviour in diffferent situations.
Run this file as:
julia init_me.jl
julia --project=@. init_me.jl
julia --project=. init_me.jl
Try running in a folder that has or does not have Project.toml file.
"""
MESSAGE = Dict(true => " (exists)", false => " (does not exist)")
exist(path)::Bool = isfile(path) || isdir(path)
printexist(path::String) = println(" ", path, MESSAGE[exist(path)])
printexist(nothing) = println("nothing")
printf2(s,n=8) = print(" " * s * ' '^(n-length(s)))
p_ = Base.JLOptions().project
project_option = (p_ != C_NULL) ? unsafe_string(p_) : "option not provided"
println("--project:\n ", project_option)
println("load_path():")
for path in Base.load_path()
printexist(path)
end
println("Base.active_project():")
printexist(Base.active_project())
println("Base.current_project():")
printexist(Base.current_project())
println("alias expansion with Base.load_path_expand():")
for alias in ["@.", "@", "@stdlib", "@v1.0"]
printf2(alias)
printexist(Base.load_path_expand(alias))
end
的行为。
init_me.jl:
julia --project=@. init_me.jl
结果如下:
julia --project=. init_me.jl
产生最期望的结果Project.toml
在路径具有非ASCII字符的文件夹上失败--project=<some dir without Project.toml>
的文件夹可以成为Base.active_project()
上的活跃项目Base.current_project()
不是qazxswpoi