在命令行中启动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
符号属于同一扩展家族吗?
答案 0 :(得分:4)
--project
--project
标志定义“家庭项目”或“家庭环境”。环境由Project.toml
/ Manifest.toml
定义,并定义using
/ import
可用的软件包。
您可以将--project
设置为(i)目录(有或没有Project.toml
)(ii)Project.toml
的路径或(iii)到@.
。 (i)和(ii)很不言自明-Julia将把位于路径上的项目视为家庭项目。现在,对于(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
文件。使用@.
选项,Julia首先在当前目录中查找Project.toml
文件,如果找不到,则将其上移到父文件夹并在其中查找,依此类推。这就是第二个示例中发生的情况。朱莉娅没有在空的Project.toml
目录中找到A
文件,因此我们移至父目录,并找到了那里的Project.toml
。
是的,我们可以为此选择其他一些令牌,但是.
则没有,因为它已经具有含义。它是当前目录的路径,并且是与--project
一起使用的完全有效的路径。
"@"
要加载包Example
,仅在其Example
部分中用[deps]
定义一个主项目是不够的;主页项目还需要显示在Julias加载路径(Base.load_path()
)中。默认情况下,加载路径从["@", "@v#.#", "@stdlib"]
展开,其中"@v#.#"
扩展到~/.julia/environments/v#.#
,其中#
替换为Julias主版本号和次要版本号,而"@stdlib"
扩展到Julias标准库的目录。 "@"
扩展为1.活动项目(通过Pkg.activate
/ pkg> activate
激活)或2.主页项目。我们可以使用Base.load_path()
检查扩展的加载路径:
# 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[]
答案 1 :(得分:0)
基于@fredrikekre答案,编写了一个脚本来探索get_field
,Base.load_path()
,Base.active_project()
的行为。
init_me.jl:
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
会产生最理想的结果julia --project=@. init_me.jl
在路径包含非ASCII字符的文件夹上失败julia --project=. init_me.jl
的文件夹可以在Project.toml
上成为活动项目--project=<some dir without Project.toml>
不是Base.active_project()