Module 如何在编辑后在活动会话中重新加载模块?

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/")

2018年更新:一定要检查所有回复,因为这个问题的答案多年来已经改变了多次。在本次更新时,
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