Mise à jour 2018: Assurez-vous de vérifier toutes les réponses, car la réponse à cette question a changé plusieurs fois au fil des ans. Au moment de cette mise à jour, la réponse Revise.jl
Est probablement la meilleure solution.
J'ai un fichier "/SomeAbsolutePath/ctbTestModule.jl", dont le contenu est:
module ctbTestModule
export f1
f1(x) = x + 1
end
Je lance Julia dans un terminal qui exécute "~/.juliarc.jl". Le code de démarrage comprend la ligne:
Push!(LOAD_PATH, "/SomeAbsolutePath/")
Par conséquent, je peux immédiatement taper dans la console Julia:
using ctbTestModule
pour charger mon module. Comme prévu, f1(1)
renvoie 2
. Maintenant, je décide soudainement que je veux modifier f1
. J'ouvre "/SomeAbsolutePath/ctbTestModule.jl" dans un éditeur et change le contenu en:
module ctbTestModule
export f1
f1(x) = x + 2
end
J'essaie maintenant de recharger le module dans ma session Julia active. J'essaie
using ctbTestModule
mais f1(1)
renvoie toujours 2
. Ensuite j'essaye:
reload("ctbTestModule")
comme suggéré ici , mais f1(1)
renvoie toujours 2
. Enfin, j'essaye:
include("/SomeAbsolutePath/ctbTestModule.jl")
comme suggéré ici , ce qui est pas idéal car je dois taper le chemin absolu complet car le répertoire actuel n'est peut-être pas "/ SomeAbsolutePath". Je reçois le message d'avertissement Warning: replacing module ctbTestModule
Qui semble prometteur, mais f1(1)
renvoie toujours 2
.
Si je ferme la session Julia en cours, que j'en démarre une nouvelle et que je tape using ctbTestModule
, J'obtiens maintenant le comportement souhaité, c'est-à-dire que f1(1)
renvoie 3
. Mais évidemment, je veux faire ça sans redémarrer Julia.
Alors, qu'est-ce que je fais mal?
Autres détails: Julia v0.2 sur Ubuntu 14.04.
La base de ce problème est la confluence de recharger un module, mais de ne pas pouvoir redéfinir quelque chose dans le module Main ( voir la documentation ici ) - c'est-à-dire au moins jusqu'à ce que le nouvel espace de travail de fonction () soit disponible le 13 juillet 2014. Versions récentes de la version 0.3 la version devrait l'avoir.
Considérez le module simpliste suivant
module TstMod
export f
function f()
return 1
end
end
Ensuite, utilisez-le ....
Julia> using TstMod
Julia> f()
1
Si la fonction f () est remplacée par retourne 2 et que le module est rechargé, f est en fait mis à jour. Mais pas redéfini dans le module Main .
Julia> reload("TstMod")
Warning: replacing module TstMod
Julia> TstMod.f()
2
Julia> f()
1
Les avertissements suivants clarifient le problème
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
Cependant, la nouvelle fonction espace de travail () efface Main le préparer pour le rechargement TstMod
Julia> workspace()
Julia> reload("TstMod")
Julia> using TstMod
Julia> f()
2
En outre, le précédent Main est stocké sous la forme LastMain
Julia> whos()
Base Module
Core Module
LastMain Module
Main Module
TstMod Module
ans Nothing
Julia> LastMain.f()
1
Utilisez le package Revise
, par exemple.
Pkg.add("Revise") # do this only once
include("src/my_module.jl")
using Revise
import my_module
Vous devrez peut-être le démarrer dans une nouvelle session REPL. Notez l'utilisation de import
au lieu de using
, car using
ne redéfinit pas la fonction dans le module Main
(comme expliqué par @Maciek Leks et @waTeim).
Autres solutions : Deux avantages de Revise.jl
Par rapport à workspace()
sont que (1) c'est beaucoup plus rapide, et (2) il est à l'épreuve du temps, car workspace()
a été déprécié en 0.7, comme discuté dans ce problème GitHub :
Julia> VERSION
v"0.7.0-DEV.3089"
Julia> workspace()
ERROR: UndefVarError: workspace not defined
et un contributeur GitHub a recommandé Revise.jl
:
Devrions-nous ajouter un message comme "l'espace de travail est obsolète, consultez plutôt Revise.jl"?
Même dans Julia 0.6.3, les trois solutions précédentes de workspace()
, import
et reload
échouent lorsqu'un module appelle d'autres modules, tels que DataFrames
. Avec les trois méthodes, j'ai eu la même erreur lorsque j'ai appelé ce module la deuxième fois dans le même REPL:
ERROR: LoadError: MethodError: all(::DataFrames.##58#59, ::Array{Any,1}) is ambiguous. Candidates: ...
J'ai également reçu de nombreux messages d'avertissement tels que:
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.
Le redémarrage de la session Julia a fonctionné, mais c'était lourd. J'ai trouvé ce problème dans le package Reexport , avec un message d'erreur similaire:
MethodError: all(::Reexport.##2#6, ::Array{Any,1}) is ambiguous.
et a suivi la suggestion d'un contributeur:
Est-ce que cela se produit sans utiliser workspace ()? Cette fonction est connue pour interagir mal avec les packages, c'est pourquoi elle a été dépréciée en 0.7.
À mon humble avis, la meilleure façon est d'utiliser import
dès le début au lieu de using
pour le problème signalé.
Considérez le module:
module ModuleX1
export produce_text
produce_text() = begin
println("v1.0")
end
println("v1.0 loaded")
end
Puis dans REPL:
Julia> import ModuleX1
v1.0 loaded
Julia> ModuleX1.produce_text()
v1.0
Mettez à jour le code du module et enregistrez-le:
module ModuleX1
export produce_text
produce_text() = begin
println("v2.0")
end
println("v2.0 loaded")
end
Ensuite, dans le REPL:
Julia> reload("ModuleX1")
Warning: replacing module ModuleX1
v2.0 loaded
Julia> ModuleX1.produce_text()
v2.0
Avantages de l'utilisation de import
par rapport à using
:
workspace()
pour se débarrasser de l'ambiguïtéInconvénients de l'utilisation de import
sur using
:
Modifié: ignoré "accès complet au module, même aux noms non exportés" de "Inconvénients ..." selon la conversation ci-dessous.
Dans Julia v0.6. il semble que l'utilisation de workspace () est non plus nécessaire: je peux simplement recharger (MyModule) dans une session REPL active, et cela fonctionne comme prévu (les modifications apportées au fichier source qui contient MyModule sont reflétées dans la session REPL) active).
Cela s'applique aux modules qui ont été intégrés dans la portée par import ou sing
Je voulais créer un nouveau module à partir de zéro, et j'ai essayé les différentes réponses avec 1.0 et je n'ai pas obtenu de résultat satisfaisant, mais j'ai trouvé que ce qui suit fonctionnait pour moi:
Depuis Julia REPL dans le répertoire que je veux utiliser pour mon projet que je lance
pkg> generate MyModule
Cela crée un sous-répertoire comme la structure suivante:
MyModule
├── Project.toml
└── src
└── MyModule.jl
J'ai mis mon code de module dans MyModule.jl
. Je passe dans le répertoire MyModule
(ou l'ouvre dans mon IDE) et j'ajoute un fichier Scratch.jl
avec le code suivant:
Pkg.activate(“.”)
using Revise
import MyModule
Ensuite, je peux ajouter mon code pour tester ci-dessous et tout se met à jour sans recharger le REPL.