如何导入自定义模块中的朱莉娅

问题描述:

我有一个模块,我在这里写下:如何导入自定义模块中的朱莉娅

# Hello.jl 
module Hello 
    function foo 
     return 1 
    end 
end 

# Main.jl 
using Hello 
foo() 

当我运行Main模块:

$ julia ./Main.jl 

我得到这个错误:

ERROR: LoadError: ArgumentError: Hello not found in path 
in require at ./loading.jl:249 
in include at ./boot.jl:261 
in include_from_node1 at ./loading.jl:320 
in process_options at ./client.jl:280 
in _start at ./client.jl:378 
while loading /Main.jl, in expression starting on line 1 

你应该include("./Hello.jl")以前using Hello

+3

那么'使用'的意义是什么?我认为这个kw会包含我的模块... – dopatraman

+0

@dopatraman'using'是将一个模块的名字引入当前作用域,而模块本身不会被include()'automaticlly(除了那些在“LOAD_PATH”) –

+0

如果你在'module'中有定义,你也需要导出它们。 – m33lky

如果你想在模块的标题“使用”你需要添加“出口富”导入模块时访问函数foo。

除非您明确加载文件(include("./Hello.jl"))Julia会在LOAD_PATH变量中定义的目录中查找模块文件。

请参阅this page

已经有一些简短的答案,但我想提供一个更完整的答案,如果可能的话。

当您运行using MyModule时,Julia只在名为LOAD_PATH的目录列表中搜索它。如果您在朱莉娅REPL键入LOAD_PATH,你会得到类似如下:

2-element Array{ByteString,1}: 
"/Applications/Julia-0.4.5.app/Contents/Resources/julia/local/share/julia/site/v0.4" 
"/Applications/Julia-0.4.5.app/Contents/Resources/julia/share/julia/site/v0.4" 

这些是朱莉娅将搜索模块,当你输入using Hello包含的目录。在您提供的示例中,由于Hello不在您的LOAD_PATH中,Julia无法找到它。

如果您希望包含本地模块,则可以指定其相对于当前工作目录的位置。

julia> include("./src/Hello.jl") 

一旦包含文件,就可以正常运行using Hello以获得所有相同的行为。对于一个脚本,这可能是最好的解决方案。但是,如果您发现自己经常不得不include()某一组目录,您可以永久将它们添加到您的LOAD_PATH

添加目录LOAD_PATH

手动添加目录到您的LOAD_PATH可以是一个痛苦,如果你想经常使用存储的朱莉娅LOAD_PATH之外的特定模块。在这种情况下,您可以将其他目录附加到LOAD_PATH环境变量。每当您发出importusing命令时,Julia都会自动搜索这些目录。

执行此操作的一种方法是将以下内容添加到您的.basrc,.profile,.zshrc

export JULIA_LOAD_PATH="/path/to/module/storage/folder" 

这会将该目录追加到Julia将搜索的标准目录中。如果你再运行

julia> LOAD_PATH 

它应该返回

3-element Array{ByteString,1}: 
"/path/to/module/storage/folder" 
"/Applications/Julia-0.4.5.app/Contents/Resources/julia/local/share/julia/site/v0.4" 
"/Applications/Julia-0.4.5.app/Contents/Resources/julia/share/julia/site/v0.4" 

现在,您可以*运行using Hello和Julia会自动查找模块(只要它被存储下面/path/to/module/storage/folder

更多信息,请看Julia Docs的this页面

虽然张实唯的回答是最接近的enient,您不应该在REPL之外使用include。如果您正在编写程序文件,请仔细阅读将相应目录添加到LOAD_PATH的问题。雷米对此如何做出了很好的解释,但也值得解释一下为什么你应该这样做。 (此外从文档:push!(LOAD_PATH, "/Path/To/My/Module/")但要注意你的模块和文件必须具有相同的名称)

的问题是什么,你include将正确的,你叫include即使是在其他地方也定义的定义。由于模块的目标是重复使用,因此最终可能会在多个文件中使用MyModule。如果在每个文件中调用include,那么每个文件都将有自己的MyModule定义,即使它们是相同的,这些定义也会不同。这意味着在MyModule(如数据类型)中定义的任何数据将不会相同。

为了说明为什么这是一个巨大的问题,考虑这三个文件:

types.jl

module TypeModule 
struct A end 
export A 
end 

a_function.jl

include("types.jl") 
module AFunctionModule 
using TypeModule 
function takes_a(a::A) 
    println("Took A!") 
end 
export takes_a 
end 

function_caller.jl

include("a_function.jl") 
include("types.jl") 
using TypeModule, AFunctionModule 
my_a = A() 
takes_a(my_a) 

如果您运行julia function_caller.jl你会得到MethodError: no method matching takes_a(::TypeModule.A)。这是因为function_caller.jl中使用的类型A与a_function.jl中使用的类型不同。在这种简单的情况下,你可以通过在function_caller.jl中反转包含的顺序来实际“修复”问题(或者只需从function_caller.jl中完全删除include("types.jl")!这不太好!)。但是如果你想要另一个文件b_function.jl,它也使用了TypeModule中定义的类型?你将不得不做一些非常冒险的事情。或者你可以修改你的LOAD_PATH,这样该模块只定义一次。