I am having trouble to include a file. More precisely isfile(fi)
returns true, but include(fi)
errors
ERROR: LoadError: could not open file C:\temp\a\SomePackage\src\src\file.jl
I created an MWE here.
I simply run julia --startup-file=no --track-allocation=user mwe_include_error.jl
in PowerShell (from the src directory)
Is this expected not to work?
It is quite irritating that isfile
returns true, but the include command fails.
You example works for me:
julia> include(fi)
hello there
Are you on Windows?
Any idea why it fails for me?
have you actually done the same call (i.e. run julia with the argument mwe_include_error.jl)?
No, I didnāt, I get the same as you. From the docstring of include
:
include(path::AbstractString)
Evaluate the contents of the input source file in the global scope
of the containing module. Every module (except those defined with
baremodule) has its own 1-argument definition of include, which
evaluates the file in that module. Returns the result of the last
evaluated expression of the input file. During including, a task-local
include path is set to the directory containing the file. Nested calls to
include will search relative to that path. This function is typically
used to load source interactively, or to combine files in packages
that are broken into multiple source files.
Use Base.include to evaluate a file into another module.
I guess what is happening here is that when you execute julia file.jl
there will be a nested include, and when you include from file.jl paths are relative that file.
2 Likes
I would vote for include and isfile to be consistent in the way that relative paths are resolved.
Would you agree?
Nah, you probably want the current behavior. You can work with absolute paths instead of relative paths.
1 Like
Well is there an easy way to make the path absolute?
Notably I am handing the same argument (a relative path) to isfile and include. But it is treated differently.
help?> abspath
abspath(path::AbstractString) -> AbstractString
Convert a path to an absolute path by adding the current directory
if necessary. Also normalizes the path as in normpath.
1 Like
I did not execute julia file.jl
I ran julia --startup-file=no .\mwe_include_error.jl
Have you tried that?
file.jl
was just a placeholder.
I feel like your āmodelā is a little wrong. Normally julia files are in specific locations. So if a file does:
include("../file1.jl")
It expects to find file1.jl in the parent directory of the currently executing fileā¦not in the parent directory of the current path. Otherwise one file changing the current directory would break all the includes for other files. i.e. If someone did this:
main.jl:
include("f1.jl")
include("f2.jl")
include("f3.jl")
f1.jl:
cd("c:\\")
f2.jl
cd("c:\\temp")
f3.jl:
println("hello")
This would just not work unless main.jl
knows that f1.jl
will change the directory, and that f2.jl
will also change the directory. What it would create is a nightmare of āfile not foundā situations where you are going to have to display the current directory before every include just to make sure the current directory is what you expected before you do the include.
I would suggest looking into include_string
where the file can be loaded first with something like read(filename, String)
then passed to include_string
. By using read
the found/not found behavior of isfile
will match with read
.
2 Likes
I think you missed the fact that include
operates relative to @__DIR__
, which has nothing to do with the ācurrent directoryā, which is essentially a global state. Cf
$ pwd
/home/tamas
$ cat /tmp/test.jl
@info "working directory" pwd()
@info "directory of file" @__DIR__
$ julia /tmp/test.jl
ā Info: working directory
ā pwd() = "/home/tamas"
ā Info: directory of file
ā #= /tmp/test.jl:2 =# @__DIR__ = "/tmp"
As explained by @pixel27, conflating the two would have obvious disadvantages ā global state should be avoided unless absolutely necessary.
1 Like
So letās say I have a number of functions (readdlm, writedlm, CSV.read, isfile, include, rm, ā¦).
Is there an easy way to find out whether these work relative to ācurrent dirā or @__DIR__
?
I think that basically everything that uses built-in I/O (think of open
) will resolve paths relative to the current directory if necessary, but relying on this is not very good style.
You should always provide full paths if possible. If you are loading a lot of files from your package directory, it is worth it to define something like
project_path(parts...) = normpath(joinpath(@__DIR__, "..", parts...))
in one of the files in src/
and then use it to construct paths.
Thank you.
I think my confusion was āinitiatedā by the fact that I have used the include command in an interactive VS Code session. In that case, I think, the include function is not relative to the file its in (as there is no such file), but relative to the working dir.
Only code loading (include
) is relative to the current source file. Everything else is a normal file operation and works relative to the current working directory.