J'ai un module que j'ai écrit ici:
# Hello.jl
module Hello
function foo
return 1
end
end
et
# Main.jl
using Hello
foo()
Lorsque j'exécute le module Main
:
$ Julia ./Main.jl
Je reçois cette erreur:
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
Vous devriez include("./Hello.jl")
avant using Hello
Il y a déjà eu quelques réponses courtes, mais je voulais donner une réponse plus complète si possible.
Lorsque vous exécutez using MyModule
, Julia ne le recherche que dans une liste de répertoires appelée LOAD_PATH
. Si vous tapez LOAD_PATH
dans Julia REPL, vous obtiendrez le résultat suivant:
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"
Ce sont les répertoires que Julia recherchera pour les modules à inclure lorsque vous tapez using Hello
. Dans l'exemple que vous avez fourni, étant donné que Hello
n'était pas dans votre LOAD_PATH
, Julia n'a pas pu le trouver.
Si vous souhaitez inclure un module local, vous pouvez spécifier son emplacement par rapport à votre répertoire de travail actuel.
Julia> include("./src/Hello.jl")
Une fois le fichier inclus, vous pouvez exécuter using Hello
normalement pour obtenir le même comportement. Pour certains scripts, c'est probablement la meilleure solution. Toutefois, si vous vous retrouvez régulièrement devant include()
avec un certain ensemble de répertoires, vous pouvez les ajouter définitivement à votre LOAD_PATH
.
Ajout de répertoires à LOAD_PATH
Ajouter manuellement des répertoires à votre LOAD_PATH
peut s'avérer difficile si vous souhaitez utiliser régulièrement des modules particuliers stockés en dehors du Julia LOAD_PATH
. Dans ce cas, vous pouvez ajouter des répertoires supplémentaires à la variable d'environnement LOAD_PATH
. Julia effectuera alors automatiquement une recherche dans ces répertoires à chaque fois que vous lancerez une commande import
ou using
.
Une façon de faire est d'ajouter ce qui suit à votre .basrc
, .profile
, .zshrc
.
export Julia_LOAD_PATH="/path/to/module/storage/folder"
Cela ajoutera ce répertoire aux répertoires standard que Julia recherchera. Si vous courez alors
Julia> LOAD_PATH
Il devrait revenir
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"
Vous pouvez maintenant exécuter librement using Hello
et Julia trouvera automatiquement le module (tant qu'il est stocké sous /path/to/module/storage/folder
.
Pour plus d'informations, consultez la page this des documents Julia.
Il existe une nouvelle réponse à cette question depuis la publication de Julia v0.7 et v1.0 qui est légèrement différente. Je devais simplement faire cela, alors je me suis dit que je posterais mes découvertes ici.
Comme déjà expliqué dans d'autres solutions, il est nécessaire d'inclure le script approprié qui définit le module. Toutefois, le module personnalisé n'étant pas un package, il ne peut pas être chargé en tant que package avec les mêmes commandes using
ou import
, comme cela pouvait être le cas dans les anciennes versions de Julia.
Donc, le script Main.jl serait écrit avec une importation relative comme ceci:
include("./Hello.jl")
using .Hello
foo()
J'ai trouvé cela expliqué simplement dans le commentaire du discours de Stefan Karpinski sur une question similaire. Comme il le décrit, la situation peut également devenir plus complexe lorsqu'il s'agit de sous-modules. La section documentation sur les chemins de modules est également une bonne référence.
Bien que la réponse de 张 实 唯 soit la plus pratique, vous ne devriez pas utiliser include
en dehors de REPL. Si vous écrivez un fichier de programme, évitez d'ajouter le répertoire approprié à LOAD_PATH. Remy donne une très bonne explication sur la façon de procéder, mais il convient également d'expliquer pourquoi vous devriez le faire en premier lieu. (De plus, à partir de la documentation: Push!(LOAD_PATH, "/Path/To/My/Module/")
, mais notez que votre module et votre fichier doivent avoir le même nom)
Le problème est que tout ce que vous include
sera défini là où vous appelez include
même s'il est également défini ailleurs. Dans la mesure où l'objectif des modules est de réutiliser, vous utiliserez probablement éventuellement MyModule
dans plusieurs fichiers. Si vous appelez include
dans chaque fichier, chacun aura sa propre définition de MyModule et, même si elles sont identiques, il s'agira de définitions différentes. Cela signifie que toutes les données définies dans la variable MyModule
(telles que les types de données) ne seront pas les mêmes.
Pour comprendre pourquoi il s’agit d’un énorme problème, considérons ces trois fichiers:
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)
Si vous exécutez Julia function_caller.jl
, vous obtiendrez MethodError: no method matching takes_a(::TypeModule.A)
. En effet, le type A
utilisé dans function_caller.jl est différent de celui utilisé dans a_function.jl. Dans ce cas simple, vous pouvez réellement "régler" le problème en inversant l'ordre des inclus dans function_caller.jl (ou simplement en supprimant include("types.jl")
entièrement de function_caller.jl! Ce n'est pas bon!). Mais que faire si vous vouliez un autre fichier b_function.jl qui utilisait également un type défini dans TypeModule
? Vous auriez à faire quelque chose de très hacky. Ou vous pouvez simplement modifier votre LOAD_PATH pour que le module ne soit défini qu'une seule fois.
EDIT en réponse à xji: Pour distribuer un module, utilisez Pkg
( docs ). J'ai compris que la prémisse de cette question était un module personnalisé et personnel.
Incidemment, si vous n’aimez vraiment pas l’idée de modifier votre chemin de chargement (même si cela n’appartient qu’à un script unique ...), vous pouvez créer un lien symbolique vers votre module dans un répertoire de paquetage (par exemple, ~/.Julia/v0.6/MyModule/MyModule.jl
), puis Pkg.add(MyModule)
, puis importer comme d'habitude. Je trouve cela un peu plus difficile.
À moins de charger explicitement le fichier (include("./Hello.jl")
), Julia recherche les fichiers de module dans les répertoires définis dans la variable LOAD_PATH.
Voir cette page .
Si vous souhaitez accéder à la fonction foo lors de l'importation du module avec "using", vous devez ajouter "export foo" dans l'en-tête du module.