Résolue

Problème d'import avec Typer

# Résolution d'erreurs # Modules # Scripting

Bonjour à tous,

je suis en train de m'amuser à faire une app avec typer et je bloque bêtement sur un import...

La structure de mon paquet:

Le contenu de mon fichier ____init.py____:

__app_name__ = 'my_cli_library'
__version__ = '0.1.0'

Le contenu de mon fichier cli.py:

from typing import Optional

import typer

from library import __app_name__, __version__


app = typer.Typer(no_args_is_help=True)


def _version_callback(value: bool) -> None:
    if value:
        typer.echo(f'{__app_name__} v{__version__}')
        raise typer.Exit()


@app.callback()
def main(
        version: Optional[bool] = typer.Option(
            None,
            '--version',
            '-v',
            help='Show the application version.',
            callback=_version_callback,
            is_eager=True,
        )
) -> None:
    return


if __name__ == '__main__':
    app()

Lorsque je lance python cli.py, j'obtiens l'erreur suivante:

    from library import __app_name__, __version__
ModuleNotFoundError: No module named 'library'

Merci d'avance! :)

Thibault houdon

Mentor

Salut David,

Ahhh les imports, c'est toujours un casse-tête ^^

Il y a plusieurs choses à comprendre ici. Quand tu lances ton script cli.py, Python va ajouter le dossier parent dans ton pythonpath (tu peux t'en rendre compte en faisant un import de sys et un print de sys.path).

Du coup, ton dossier library sera dans ton pythonpath, ce qui te permet d'importer depuis les fichiers contenus à l'intérieur de ce dossier (donc config, datbase, etc).

Mais pas depuis library !

Si je fais un print de mon sys.path ça me donne ça :

['/Users/thibh/Documents/library', '/Library/Frameworks/Python.framework/Versions/3.12/lib/python312.zip', '/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12', '/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/lib-dynload', '/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages']

Tu vois que le dossier library apparaît bien en premier, donc tu peux importer tout ce qui est à l'intérieur mais library lui-même, non.

Ce que tu peux faire : te déplacer dans le dossier Documents (dans mon cas spécifique ici) et exécuter ton fichier en tant que module (-m) :

cd /Users/thibh/Documents
python3 -m library.cli

Dans ce cas-ci, c'est le dossier Documents qui sera en premier dans le pythonpath et tu pourras donc faire ton from library import __app_name__, __version__. Tu pourrais aussi faire un import relatif avec from . import __app_name__, __version__.

Comme je vois que tu as déjà un fichier __main__.py tu pourrais aussi t'en servir.

Tu aurais quelque chose du genre :

# cli.py
from . import __app_name__, __version__

def app():
    print(__app_name__, __version__)
# __main__.py
from .cli import app

if __name__ == "__main__":
    app()

Et tu peux ensuite lancer directement ton module library :

python3 -m library

Salut Thibault!
Merci beaucoup pour ta réponse très détaillée!!!

Je vois qu'il y a un vrai boulot à faire sur les imports de mon côté... je croyais avoir compris le concept globalement, mais visiblement pas! Direction donc la doc pour tout reprendre sur ce point!

Par contre, ce qui est étrange, c'est que j'avais déjà testé les imports relatifs, et ça ne fonctionnait pas.
Si je fais un:

# cli.py
from . import __app_name__, __version__

j'obtiens le message d'erreur suivant:
ImportError: attempted relative import with no known parent package

Inscris-toi

(c'est gratuit !)

Inscris-toi

Tu dois créer un compte pour participer aux discussions.

Créer un compte

Rechercher sur le site

Formulaire de contact

Inscris-toi à Docstring

Pour commencer ton apprentissage.

Tu as déjà un compte ? Connecte-toi.