2018更新:请务必检查所有回复,因为多年来此问题的答案已多次更改。在此次更新时,Revise.jl
答案可能是最佳解决方案。
我有一个文件“/SomeAbsolutePath/ctbTestModule.jl”,其内容是:
module ctbTestModule
export f1
f1(x) = x + 1
end
我在一个运行“〜/ .juliarc.jl”的终端中启动了Julia。启动代码包括以下行:
push!(LOAD_PATH, "/SomeAbsolutePath/")
因此我可以立即输入Julia控制台:
using ctbTestModule
加载我的模块。按预期f1(1)
返回2
。现在我突然决定要编辑f1
。我在编辑器中打开“/SomeAbsolutePath/ctbTestModule.jl”,并将内容更改为:
module ctbTestModule
export f1
f1(x) = x + 2
end
我现在尝试在我的活跃Julia会话中重新加载模块。我试试
using ctbTestModule
但f1(1)
仍会返回2
。接下来我试试:
reload("ctbTestModule")
按照建议here,但f1(1)
仍然返回2
。最后,我尝试:
include("/SomeAbsolutePath/ctbTestModule.jl")
建议here,不理想,因为我必须输入完整的绝对路径,因为当前目录可能不是“/ SomeAbsolutePath”。我收到了警告信息Warning: replacing module ctbTestModule
,这听起来很有希望,但f1(1)
仍然会返回2
。
如果我关闭当前的Julia会话,启动一个新会话并输入using ctbTestModule
,我现在可以获得所需的行为,即f1(1)
返回3
。但显然我想这样做没有重新启动Julia。
那么,我做错了什么?
其他细节:Ubuntu 14.04上的Julia v0.2。
答案 0 :(得分:52)
此问题的基础是重新加载模块的汇合,但无法重新定义模块 Main (see the documentation here)中的内容 - - 这是at least until the new function workspace() was made available于2014年7月13日。最新版本的0.3预发布应该有它。
考虑以下简单模块
module TstMod
export f
function f()
return 1
end
end
然后使用它....
julia> using TstMod
julia> f()
1
如果功能 f ()更改为返回2 并重新加载模块,则 f 实际上已更新。但未在模块 Main 中重新定义。
julia> reload("TstMod")
Warning: replacing module TstMod
julia> TstMod.f()
2
julia> f()
1
以下警告可以解决问题
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
但是,新功能工作区()清除 主 ,准备重新加载 TstMod < /强>
julia> workspace()
julia> reload("TstMod")
julia> using TstMod
julia> f()
2
此外,之前的 Main 存储为 LastMain
julia> whos()
Base Module
Core Module
LastMain Module
Main Module
TstMod Module
ans Nothing
julia> LastMain.f()
1
答案 1 :(得分:10)
我认为,更好的方法是从一开始就使用import
而不是using
来报告问题。
考虑模块:
module ModuleX1
export produce_text
produce_text() = begin
println("v1.0")
end
println("v1.0 loaded")
end
然后在REPL:
julia> import ModuleX1
v1.0 loaded
julia> ModuleX1.produce_text()
v1.0
更新模块的代码并保存:
module ModuleX1
export produce_text
produce_text() = begin
println("v2.0")
end
println("v2.0 loaded")
end
接下来,在REPL中:
julia> reload("ModuleX1")
Warning: replacing module ModuleX1
v2.0 loaded
julia> ModuleX1.produce_text()
v2.0
使用import
优于using
的优势:
workspace()
使用import
而不是using
的缺点:
编辑:放弃&#34;完全访问模块,甚至是未导出的名称&#34;来自&#34;缺点......&#34;根据下面的对话。
答案 2 :(得分:10)
使用包Revise
,例如
Pkg.add("Revise") # do this only once
include("src/my_module.jl")
using Revise
import my_module
您可能需要在新的REPL会话中启动它。请注意使用import
而不是using
,因为using
未重新定义Main
模块中的函数(如@Maciek Leks和@waTeim所述)。
其他解决方案:Revise.jl
与workspace()
相比的两个优点是(1)它更快,(2)它是面向未来的,因为{ {1}}已弃用,如this GitHub issue中所述:
workspace()
并且GitHub撰稿人建议julia> VERSION
v"0.7.0-DEV.3089"
julia> workspace()
ERROR: UndefVarError: workspace not defined
:
我们是否应该添加一些消息,例如“工作空间已弃用,请查看Revise.jl”?
即使在Julia 0.6.3中,Revise.jl
,workspace()
和import
之前的三个解决方案在模块调用其他模块时失败,例如reload
。使用这三种方法,当我在同一个REPL中第二次调用该模块时,我得到了同样的错误:
DataFrames
我还收到许多警告信息,例如:
ERROR: LoadError: MethodError: all(::DataFrames.##58#59, ::Array{Any,1}) is ambiguous. Candidates: ...
重新启动Julia会话有效,但很麻烦。我找到了this issue in the Reexport package,其中包含类似的错误消息:
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.
并遵循一位撰稿人的建议:
不使用workspace()会发生这种情况吗?该函数因与软件包交互不佳而臭名昭着,这也是它在0.7中被弃用的部分原因。
答案 3 :(得分:7)
在julia v0.6.0 中,似乎使用 workspace()需要更长时间没有:我只需重新加载(MyModule) )在一个活动的REPL会话中,它按预期工作(对包含MyModule的源文件的chages反映在活动的REPL会话中)。
这适用于已通过导入或使用
进入范围的模块答案 4 :(得分:0)
我想从头开始创建一个新模块,并尝试使用1.0的不同答案,但未获得令人满意的结果,但是我发现以下方法对我有用:
在我要用于我的项目的目录中的Julia REPL中
pkg> generate MyModule
这将创建一个类似于以下结构的子目录:
MyModule
├── Project.toml
└── src
└── MyModule.jl
我将模块代码放入MyModule.jl
中。我转到目录MyModule
(或在我的IDE中打开它),并使用以下代码添加文件Scratch.jl
:
Pkg.activate(“.”)
using Revise
import MyModule
然后,我可以在下面添加我的代码进行测试,并且所有内容都会更新,而无需重新加载REPL。