karei
2024 年7 月 21 日 09:46
1
在开发时经常修改代码,为了不让过多的函数和类型定义污染全局命名空间,大部分函数和类型我都放在模块里了。问题是修改模块后重新运行不生效,每次都要重启REPL。例如有这样一个模块
module my_module
export Person, test1
struct Person
name::String
end
function test1(a::Person)
println("a's name $(a.name)")
end
end
和一个主函数
include("my_module.jl")
using .my_module
a = Person("David")
test1(a)
按照JuliaFAQ 中的说法,将类型用模块裹起来就可以随时修改类型了。但是当我将代码修改如下后重新运行,类型定义并不更新,函数的修改也不生效。至少来说在全局作用域的函数只要重新运行一遍函数定义就可以生效了,但是在模块里的类型和函数修改后再include也没用。在不重启REPL的前提下有什么办法吗?(用的Julia v1.10.4)
module my_module
export Person, test1
struct Person
name::String
age::Float64
end
function test1(a::Person)
println("a's age $(a.age)")
end
end
main.jl
include("my_module.jl")
using .my_module
a = Person("David",11)
test1(a)
WARNING: replacing module my_module.
WARNING: using my_module.Person in module Main conflicts with an existing identifier.
WARNING: using my_module.test1 in module Main conflicts with an existing identifier.
ERROR: MethodError: no method matching Person(::String, ::Int64)
Closest candidates are:
Person(::String)
@ Main.my_module \my_module.jl:5
Person(::Any)
karei
2024 年7 月 21 日 14:43
3
谢谢,尽管Limitations中只提到了类型、常量和同名函数和变量之间的冲突,但实际测试后我发现模块里的函数也没法被重编译(函数自身之间的冲突),我还是不用模块算了
1 个赞
karei
2024 年7 月 22 日 03:03
5
用了,具体来说,当我将下述my_module.jl中的println(a * 2)改成println(a * 3)时,输出仍然是20.
my_module.jl
module my_module
export test1
function test1(a)
println(a * 2)
end
end
main.jl
using Revise
include("my_module.jl")
using .my_module
test1(10)
修改前的输出:20
修改后的输出:WARNING: replacing module my_module.
WARNING: using my_module.test1 in module Main conflicts with an existing identifier.
20
你目录结构是标准Pkg.generate 生成的吗,按道理应该全局using Revise 然后在脚本using my_module 就行
karei
2024 年7 月 22 日 03:39
7
我没有用Pkg.generate,我是用Vscode打开一个文件夹,在里面新建了几个.jl文件就开始写代码了……我不清楚这样和使用Pkg.generate在创建模块上有什么不同
稍后我会试一下使用Pkg.generate
karei
2024 年7 月 22 日 05:16
9
感谢您的帮助,用includet问题解决了。
总结一下本贴获得的经验:
一开始出现的问题在于Revise.jl根本没有跟踪到这些被修改的模块。可以用下面的命令来查看Revise.jl跟踪了哪些模块:
julia> Revise.watched_files
在没有使用PkgTemplates.jl时,可以用includet 来跟踪指定的脚本和模块。
参考Julia 模块开发 - 保姆级教程 ,我用PkgTemplates.jl创建了一个模块“TestPackage”。
module TestPackage
export testa
function testa(a)
print(a * 3)
end
end # module TestPackage
此时,目录结构看起来类似下面这样
TestPackage
├── Manifest.toml
├── Project.toml
├── src
│ └── TestPackage.jl
└── test
└── runtests.jl
因为Project.toml里面有"TestPackage",所以可用以下命令让Revise跟踪到修改。
using Revise
using TestPackage
testa(10)
查看Revise.watched_files
可以发现TestPackage已经在列表中。
但是以下的方法不能让Revise跟踪到修改 :
using Revise
push!(LOAD_PATH, pwd() * "\\src")
using .TestPackage
# or
include("..\\src\\TestPackage.jl")
using .TestPackage
也就是说,Revise跟踪不到使用include加载的模块和从加载路径加载的模块。
参考:
1 个赞
xgdgsc
2024 年7 月 22 日 05:57
10
1 个赞