How do I reload a module in an active Julia session after an edit?
Solution 1:
The basis of this problem is the confluence of reloading a module, but not being able to redefine a thing in the module Main (see the documentation here) -- that is at least until the new function workspace() was made available on July 13 2014. Recent versions of the 0.3 pre-release should have it.
Before workspace()
Consider the following simplistic module
module TstMod
export f
function f()
return 1
end
end
Then use it....
julia> using TstMod
julia> f()
1
If the function f() is changed to return 2 and the module is reloaded, f is in fact updated. But not redefined in module Main.
julia> reload("TstMod")
Warning: replacing module TstMod
julia> TstMod.f()
2
julia> f()
1
The following warnings make the problem clear
julia> using TstMod
Warning: using TstMod.f in module Main conflicts with an existing identifier.
julia> using TstMod.f
Warning: ignoring conflicting import of TstMod.f into Main
Using workspace()
However, the new function workspace() clears Main preparing it for reloading TstMod
julia> workspace()
julia> reload("TstMod")
julia> using TstMod
julia> f()
2
Also, the previous Main is stored as LastMain
julia> whos()
Base Module
Core Module
LastMain Module
Main Module
TstMod Module
ans Nothing
julia> LastMain.f()
1
Solution 2:
Use the package Revise
, e.g.
Pkg.add("Revise") # do this only once
include("src/my_module.jl")
using Revise
import my_module
You may need to start this in a new REPL session. Notice the use of import
instead of using
, because using
does not redefine the function in the Main
module (as explained by @Maciek Leks and @waTeim).
Other solutions: Two advantages of Revise.jl
compared to workspace()
are that (1) it is much faster, and (2) it is future-proof, as workspace()
was deprecated in 0.7, as discussed in this GitHub issue:
julia> VERSION
v"0.7.0-DEV.3089"
julia> workspace()
ERROR: UndefVarError: workspace not defined
and a GitHub contributor recommended Revise.jl
:
Should we add some mesage like "workspace is deprecated, check out Revise.jl instead"?
Even in Julia 0.6.3, the three previous solutions of workspace()
, import
, and reload
fail when a module called other modules, such as DataFrames
. With all three methods, I got the same error when I called that module the second time in the same REPL:
ERROR: LoadError: MethodError: all(::DataFrames.##58#59, ::Array{Any,1}) is ambiguous. Candidates: ...
I also got many warning messages such as:
WARNING: Method definition macroexpand(Module, ANY) in module Compat at /Users/mmorin/.julia/v0.6/Compat/src/Compat.jl:87 overwritten in module Compat at /Users/mmorin/.julia/v0.6/Compat/src/Compat.jl:87.
Restarting the Julia session worked, but it was cumbersome. I found this issue in the Reexport package, with a similar error message:
MethodError: all(::Reexport.##2#6, ::Array{Any,1}) is ambiguous.
and followed the suggestion of one contributor:
Does this happen without using workspace()? That function is notorious for interacting poorly with packages, which is partly why it was deprecated in 0.7.
Solution 3:
In my humble opinion, the better way is to use import
from the very beginning instead of using
for the reported issue.
Consider the module:
module ModuleX1
export produce_text
produce_text() = begin
println("v1.0")
end
println("v1.0 loaded")
end
Then in REPL:
julia> import ModuleX1
v1.0 loaded
julia> ModuleX1.produce_text()
v1.0
Update the code of the module and save it:
module ModuleX1
export produce_text
produce_text() = begin
println("v2.0")
end
println("v2.0 loaded")
end
Next, in the REPL:
julia> reload("ModuleX1")
Warning: replacing module ModuleX1
v2.0 loaded
julia> ModuleX1.produce_text()
v2.0
Advantages of using import
over using
:
- avoiding ambiguity in function calls (What to call: ModuleX1.produce_text() or produce_text() after reloading?)
- do not have to call
workspace()
in order to get rid of ambiguity
Disadvantages of using import
over using
:
- a fully qualified name in every call for every exported name is needed
Edited: Discarded "full access to the module, even to the not-exported names" from "Disadvantages..." according to the conversation below.