Hi there – I would like to write a code that loads all data of a file, but only in case this file exists. I use the @load function of JLD2. However, integrating @load into an if statement leads to an error if the file does not exist. Does anyone have a suggestion to get around this? Here is a code example:
using JLD2
if isfile("TEST_FILE.jld2")
@load("TEST_FILE.jld2")
end
The error does not appear if jldopen is used, but @load works much better for my needs. Whatever the reason is, I am interested to load all data from a file, if the file exists (Breakpointfile from a long-running code).
Many thanks! Jonas
The problem with @load is that the opening of the file does not occur in the returned Expression, but in the body of the macro itself. Therefore, the file will be opened at parse-time, regardless of the if-statement.
@load implementation
julia> @less @load("TEST_FILE.jld2")
macro load(filename, vars...)
if isempty(vars)
if isa(filename, Expr)
throw(ArgumentError("filename argument must be a string literal unless variable names are specified"))
end
# Load all variables in the top level of the file
vars = Symbol[]
f = jldopen(filename)
try
for n in keys(f)
if !isgroup(f, lookup_offset(f.root_group, n))
push!(vars, Symbol(n))
end
end
finally
close(f)
end
end
return quote
($([esc(x) for x in vars]...),) = jldopen($(esc(filename))) do f
($([:(read(f, $(string(x)))) for x in vars]...),)
end
$(Symbol[v for v in vars]) # convert to Array
end
end
Before continuing, let me first point out that @load and @save are listed under Legacy in the documentation, and they mention that “Over time a range of issues have been opened by new users struggling with them.” In other words, it’s probably best to refactor your code to avoid @load.
That being said, you could easily ‘fix’ @load by adding your isfile(filename) check before the f = jldopen(filename) line, e.g. as isfile(filename) || return. (Note that you’ll have to import JLD2.lookup_offset, JLD2.isgroup.) Alternatively, you can move the jldopen to inside the quote. Or if you want a quick-and-dirty hack, you can delay the macro parsing, e.g. via
julia> if isfile("non_existing_file.jld2")
eval(:(@load("non_existing_file.jld2")))
end
julia> if isfile("existing_file.jld2")
eval(:(@load("existing_file.jld2")))
end
2-element Vector{Symbol}:
:hello
:xs