Module 如何在编辑后在活动会话中重新加载模块?
2018年更新:一定要检查所有回复,因为这个问题的答案多年来已经改变了多次。在本次更新时,Module 如何在编辑后在活动会话中重新加载模块?,module,julia,Module,Julia,2018年更新:一定要检查所有回复,因为这个问题的答案多年来已经改变了多次。在本次更新时,revision.jl答案可能是最好的解决方案 我有一个文件“/SomeAbsolutePath/ctbTestModule.jl”,其内容如下: module ctbTestModule export f1 f1(x) = x + 1 end 我在运行“~/.juliarc.jl”的终端中启动Julia。启动代码包括以下行: push!(LOAD_PATH, "/SomeAbsolutePath/")
revision.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")
正如建议的那样,但是f1(1)
仍然返回2
。最后,我尝试:
include("/SomeAbsolutePath/ctbTestModule.jl")
正如所建议的,这并不理想,因为我必须键入完整的绝对路径,因为当前目录可能不是“/SomeAbsolutePath”。我收到了警告消息warning:replacement module ctbTestModule
,听起来很有希望,但是f1(1)
仍然返回2
如果我关闭当前Julia会话,启动一个新会话,然后使用ctbTestModule输入,
,我现在可以获得所需的行为,即f1(1)
返回3
。但很明显,我想在不重新启动Julia的情况下这样做
那么,我做错了什么
其他细节:Ubuntu14.04上的Julia v0.2。这个问题的基础是重新加载一个模块,但无法在模块Main()中重新定义一个东西,即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
使用工作区()
但是,新功能工作区()会清除Main以准备重新加载TstMod
此外,先前的Main存储为LastMain
在我看来,更好的方法是从一开始就使用
import
,而不是对报告的问题使用
以模块为例:
module ModuleX1
export produce_text
produce_text() = begin
println("v1.0")
end
println("v1.0 loaded")
end
然后在答复中:
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
使用导入
优于使用
:
- 避免函数调用中的歧义(调用什么:ModuleX1.product_text()或重载后product_text())
- 不必调用
workspace()
来消除歧义
使用导入
而不是使用
的缺点:
- 对于每个导出的名称,每次调用都需要一个完全限定的名称
编辑:根据下面的对话,从“缺点…”中放弃了“对模块的完全访问权,甚至是对未导出的名称的访问权”。workspace()
已被弃用
您可以在活动REPL会话中重新加载(“MyModule”)
,并按预期工作:对包含MyModule
的源文件所做的更改将反映在活动REPL会话中
这适用于通过导入MyModule
或使用MyModule
使用软件包修订
而纳入范围的模块,例如
Pkg.add("Revise") # do this only once
include("src/my_module.jl")
using Revise
import my_module
您可能需要在新的REPL会话中启动此会话。请注意使用导入
而不是使用
,因为使用
不会重新定义主
模块中的函数(如@Maciek Leks和@waTeim所述)
其他解决方案:与workspace()
相比,revision.jl
的两个优点是:(1)它速度更快,(2)它是未来的证明,因为workspace()
在0.7中被弃用,如中所述:
和GitHub投稿人推荐的Revise.jl
:
我们是否应该添加一些mesage,比如“不推荐使用工作区,请查看Revise.jl”
即使在Julia 0.6.3中,workspace()
、import
和reload
这三种以前的解决方案在模块调用其他模块(如DataFrames
)时也会失败。对于这三种方法,当我在同一个REPL中第二次调用该模块时,我得到了相同的错误:
ERROR: LoadError: MethodError: all(::DataFrames.##58#59, ::Array{Any,1}) is ambiguous. Candidates: ...
我还收到了许多警告信息,如:
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.
重新启动Julia会话是有效的,但很麻烦。我发现了一条类似的错误消息:
MethodError: all(::Reexport.##2#6, ::Array{Any,1}) is ambiguous.
并遵循一位撰稿人的建议:
在不使用workspace()的情况下会发生这种情况吗?该函数因与包的交互不好而臭名昭著,这也是它在0.7中被弃用的部分原因
我想从头开始创建一个新模块,并用1.0尝试了不同的答案,但没有得到令人满意的结果,但我发现以下方法对我有效:
从我要用于我运行的项目的目录中的juliarepl
pkg> generate MyModule
这将创建类似以下结构的子目录:
MyModule
├── Project.toml
└── src
└── MyModule.jl
我将模块代码放入MyModule.jl
。我切换到目录MyModule
(或在我的IDE中打开它),并添加一个带有以下代码的文件Scratch.jl
:
using Pkg
Pkg.activate(".")
using Revise
import MyModule # or using MyModule
然后,我可以将我的代码添加到下面的测试中,所有内容都会更新,而无需重新加载REPL。+1+勾选非常感谢。一旦StackOverflow让我:-)清除,我会回来奖励赏金!()
和清除!(:TstMod)
我失败,出现错误:常数TstMod的重新定义无效
。我不知道怎么做
pkg> generate MyModule
MyModule
├── Project.toml
└── src
└── MyModule.jl
using Pkg
Pkg.activate(".")
using Revise
import MyModule # or using MyModule