J'ai une structure de répertoires similaire à la suivante
meta_project
project1
__init__.py
lib
module.py
__init__.py
notebook_folder
notebook.jpynb
Lorsque vous travaillez dans notebook.jpynb
si je tente d'utiliser une importation par rapport à accéder à une fonction function()
dans module.py
avec:
from ..project1.lib.module import function
J'obtiens l'erreur suivante:
SystemError Traceback (most recent call last)
<ipython-input-7-6393744d93ab> in <module>()
----> 1 from ..project1.lib.module import function
SystemError: Parent module '' not loaded, cannot perform relative import
Existe-t-il un moyen de faire fonctionner cela en utilisant des importations relatives?
Notez que le serveur notebook est instancié au niveau du meta_project
répertoire, il doit donc avoir accès aux informations de ces fichiers.
Notez également qu'au moins, comme prévu à l'origine, project1
n'a pas été pensé comme un module et n'a donc pas de __init__.py
fichier, il était simplement conçu comme un répertoire de système de fichiers. Si la solution au problème nécessite de le traiter comme un module et d'inclure un __init__.py
fichier (même vide), c'est bien, mais cela ne suffit pas pour résoudre le problème.
Je partage ce répertoire entre les machines et les importations relatives me permettent d'utiliser le même code partout, et j'utilise souvent des blocs-notes pour le prototypage rapide, donc les suggestions qui impliquent de pirater ensemble des chemins absolus sont peu susceptibles d'être utiles.
Edit: Ceci est différent des importations relatives dans Python 3 , qui parle d'importations relatives dans Python 3 en général et - en particulier - d'exécuter un script à partir d'un répertoire de package. Cela a à voir avec le travail dans un notebook jupyter en essayant d'appeler une fonction dans un module local dans un autre répertoire qui a à la fois des aspects généraux et particuliers différents.
__init__
fichiers dans votre répertoire de package?lib
annuaire.Réponses:
J'ai eu presque le même exemple que vous dans ce cahier où je voulais illustrer l'utilisation de la fonction d'un module adjacent de manière DRY.
Ma solution était d'indiquer à Python ce chemin d'importation de module supplémentaire en ajoutant un extrait de code comme celui-ci au notebook:
Cela vous permet d'importer la fonction souhaitée à partir de la hiérarchie des modules:
Notez qu'il est nécessaire d'ajouter des
__init__.py
fichiers vides aux dossiers project1 / et lib / si vous ne les avez pas déjà.la source
Je suis venu ici à la recherche des meilleures pratiques en matière de résumé du code dans des sous-modules lorsque vous travaillez dans des blocs-notes. Je ne suis pas sûr qu'il existe une meilleure pratique. J'ai proposé ceci.
Une hiérarchie de projet en tant que telle:
Et de
20170609-Initial_Database_Connection.ipynb
:Cela fonctionne car par défaut, le bloc-notes Jupyter peut analyser la
cd
commande. Notez que cela n'utilise pas la magie Python Notebook. Cela fonctionne simplement sans pré-ajouter%bash
.Étant donné que 99 fois sur 100 je travaille dans Docker en utilisant l'une des images Project Jupyter Docker , la modification suivante est idempotente
la source
chdir
plutôt que d'ajouter au chemin, car je suis à la fois intéressé par l'importation à partir du référentiel principal ainsi que par l'interfaçage avec certains fichiers.if os.path.isdir('../lib/'): os.chdir('../lib')
:; ou, mieux, utilisez../lib/db/
avec votrepostgres.py
afin de ne pas chdir accidentellement vers un répertoire supérieur contenant également un autrelib
.cd ..
deux fois.Jusqu'à présent, la réponse acceptée a fonctionné le mieux pour moi. Cependant, ma préoccupation a toujours été qu'il existe un scénario probable où je pourrais refactoriser le
notebooks
répertoire en sous-répertoires, nécessitant de changer lemodule_path
dans chaque bloc-notes. J'ai décidé d'ajouter un fichier python dans chaque répertoire de notebook pour importer les modules requis.Ainsi, ayant la structure de projet suivante:
J'ai ajouté le fichier
project_path.py
dans chaque sous-répertoire de notebook (notebooks/explore
etnotebooks/explain
). Ce fichier contient le code des importations relatives (depuis @metakermit):De cette façon, j'ai juste besoin de faire des importations relatives dans le
project_path.py
fichier, et non dans les cahiers. Les fichiers de notebooks auraient alors juste besoin d'être importésproject_path
avant l'importationlib
. Par exemple dans0.0-notebook.ipynb
:La mise en garde ici est que l'annulation des importations ne fonctionnerait pas. CELA NE FONCTIONNE PAS:
Il faut donc être prudent lors des importations.
la source
Je viens de trouver cette jolie solution:
Vous voulez juste quelques fonctions de ce fichier
Si la version python> = 3.3, vous n'avez pas besoin du fichier init.py dans le dossier
la source
if ".." not in sys.path: ... sys.path.insert(0,"..")
En recherchant moi-même ce sujet et après avoir lu les réponses, je recommande d'utiliser la bibliothèque path.py car elle fournit un gestionnaire de contexte pour modifier le répertoire de travail actuel.
Vous avez alors quelque chose comme
Cependant, vous pouvez simplement omettre la
isdir
déclaration.Ici, je vais ajouter des instructions d'impression pour vous permettre de suivre facilement ce qui se passe
qui sort dans cet exemple (où lib est à
/home/jovyan/shared/notebooks/by-team/data-vis/demos/lib
):Étant donné que la solution utilise un gestionnaire de contexte, vous êtes assuré de revenir à votre répertoire de travail précédent, quel que soit l'état dans lequel se trouvait votre noyau avant la cellule et quelles que soient les exceptions levées en important le code de votre bibliothèque.
la source
Voici mes 2 cents:
import sys
mappez le chemin où se trouve le fichier du module. Dans mon cas, c'était le bureau
sys.path.append ('/ Users / John / Desktop')
Soit importer tout le module de mappage MAIS alors vous devez utiliser le .notation pour mapper les classes comme mappage.
import mapping # mapping.py est le nom de mon fichier de module
shipit = mapping.Shipment () #Shipment est le nom de la classe que je dois utiliser dans le module de cartographie
Ou importez la classe spécifique depuis le module de mappage
depuis le mappage importation mappage
shipit = Shipment () #Maintenant, vous n'avez pas besoin d'utiliser le .notation
la source
J'ai trouvé que python-dotenv aide à résoudre ce problème assez efficacement. La structure de votre projet finit par changer légèrement, mais le code de votre bloc-notes est un peu plus simple et cohérent entre les blocs-notes.
Pour votre projet, faites une petite installation.
Ensuite, le projet se transforme en:
Et enfin, votre import se transforme en:
Un +1 pour ce package est que vos blocs-notes peuvent contenir plusieurs répertoires. python-dotenv trouvera le plus proche dans un répertoire parent et l'utilisera. Un +2 pour cette approche est que jupyter chargera les variables d'environnement à partir du fichier .env au démarrage. Double coup dur.
la source