How to import custom module in julia
There is a new answer to this question since the release of Julia v0.7 and v1.0 that is slightly different. I just had to do this so I figured I'd post my findings here.
As already explained in other solutions, it is necessary to include the relevant script which defines the module. However, since the custom module is not a package, it cannot be loaded as a package with the same using
or import
commands as could be done in older Julia versions.
So the Main.jl script would be written with a relative import like this:
include("./Hello.jl")
using .Hello
foo()
I found this explained simply in Stefan Karpinski's discourse comment on a similar question. As he describes, the situation can also get more elaborate when dealing with submodules. The documentation section on module paths is also a good reference.
Though 张实唯's answer is the most convenient, you should not use include
outside the REPL. If you're writing a program file, go through the trouble of adding the appropriate directory to the LOAD_PATH. Remy gives a very good explanation of how to do so, but it's worth also explaining why you should do so in the first place. (Additionally from the docs: push!(LOAD_PATH, "/Path/To/My/Module/")
but note your module and your file have to have the same name)
The problem is that anything you include
will be defined right where you call include
even if it is also defined elsewhere. Since the goal of modules is re-use, you'll probably eventually use MyModule
in more than one file. If you call include
in each file, then each will have its own definition of MyModule, and even though they are identical, these will be different definitions. That means any data defined in the MyModule
(such as data types) will not be the same.
To see why this is a huge problem, consider these three files:
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)
If you run julia function_caller.jl
you'll get MethodError: no method matching takes_a(::TypeModule.A)
. This is because the type A
used in function_caller.jl is different from the one used in a_function.jl. In this simple case, you can actually "fix" the problem by reversing the order of the includes in function_caller.jl (or just by deleting include("types.jl")
entirely from function_caller.jl! That's not good!). But what if you wanted another file b_function.jl that also used a type defined in TypeModule
? You would have to do something very hacky. Or you could just modify your LOAD_PATH so the module is only defined once.
EDIT in response to xji: To distribute a module, you'd use Pkg
(docs). I understood the premise of this question to be a custom, personal module.
Incidentally, if you really don't like the idea of modifying your load path (even if it's only within the scope of a single script...) you could symlink your module into a package directory (e.g. ~/.julia/v0.6/MyModule/MyModule.jl
) and then Pkg.add(MyModule)
and then import as normal. I find that to be a bit more trouble.
This answer has been OUTDATED. Please see other excellent explanations.
===
You should include("./Hello.jl")
before using Hello
This answers was originally written for Julia 0.4.5. There is now an easier way of importing a local file (see @kiliantics answer). However, I will leave this up as my answer explains several other methods of loading files from other directories which may be of use still.
There have already been some short answers, but I wanted to provide a more complete answer if possible.
When you run using MyModule
, Julia only searches for it in a list of directories known as your LOAD_PATH
. If you type LOAD_PATH
in the Julia REPL, you will get something like the following:
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"
These are the directories that Julia will search for modules to include when you type using Hello
. In the example that you provided, since Hello
was not in your LOAD_PATH
, Julia was unable to find it.
If you wish to include a local module, you can specify its location relative to your current working directory.
julia> include("./src/Hello.jl")
Once the file has been included, you can then run using Hello
as normal to get all of the same behavior. For one off scripts, this is probably the best solution. However, if you find yourself regular having to include()
a certain set of directories, you can permanently add them to your LOAD_PATH
.
Adding directories to LOAD_PATH
Manually adding directories to your LOAD_PATH
can be a pain if you wish to regularly use particular modules that are stored outside of the Julia LOAD_PATH
. In that case, you can append additional directories to the LOAD_PATH
environment variable. Julia will then automatically search through these directories whenever you issue an import
or using
command.
One way to do this is to add the following to your .basrc
, .profile
, .zshrc
.
export JULIA_LOAD_PATH="/path/to/module/storage/folder"
This will append that directory onto the standard directories that Julia will search. If you then run
julia> LOAD_PATH
It should return
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"
You can now freely run using Hello
and Julia will automatically find the module (as long as it is stored underneath /path/to/module/storage/folder
.
For more information, take a look at this page from the Julia Docs.
Unless you explicitly load the file (include("./Hello.jl")
) Julia looks for module files in directories defined in the LOAD_PATH variable.
See this page.