How do I reload a module in an active Julia session after an edit?
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
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.
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.