How do I reload a module in an active Julia session after an edit?

后端 未结 5 1316
青春惊慌失措
青春惊慌失措 2020-12-04 16:07

2018 Update: Be sure to check all the responses, as the answer to this question has changed multiple times over the years. At the time of this update, the <

相关标签:
5条回答
  • 2020-12-04 16:46

    In julia v0.6.0 it seems like using workspace() is no longer necessary: I can simply reload(MyModule) in an active REPL session, and it works as expected (chages made to the source file that contains MyModule are reflected in the active REPL session).

    This applies to modules that have been brought into scope by either import or using

    0 讨论(0)
  • 2020-12-04 16:48

    I wanted to create a new module from scratch, and tried the different answers with 1.0 and didn’t get a satisfactory result, but I found the following worked for me:

    From the Julia REPL in the directory I want to use for my project I run

    pkg> generate MyModule
    

    This creates a subdirectory like the following structure:

    MyModule
    ├── Project.toml
    └── src
        └── MyModule.jl
    

    I put my module code in MyModule.jl. I change to the directory MyModule (or open it in my IDE) and add a file Scratch.jl with the following code:

    Pkg.activate(“.”)
    using Revise
    import MyModule
    

    Then I can add my code to test below and everything updates without reloading the REPL.

    0 讨论(0)
  • 2020-12-04 16:50

    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.

    0 讨论(0)
  • 2020-12-04 16:55

    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
    
    0 讨论(0)
  • 2020-12-04 17:05

    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.

    0 讨论(0)
提交回复
热议问题