Importer des modules via f-string

Bonjour,

Je souhaite faire quelque chose comme ceci et ça ne passe pas :

for mod in ["pyxhook", "tkinter"]:
    try:
          import f'{mod}'
    except ImportError:
          os.system(f'pip3 install {mod}')
          import f'{mod}'
...

Comment faire ou est-ce impossible ?

pierre estrem

Le nom sur PyPI n’est pas forcément le même que le nom à importer, donc cette approche ne fonctionnera pas à tous les coups.

Quelque chose comme ça peut-être plus robuste :

https://martin.rpdev.net/2020/08/18/installing-and-using-a-pip-package-from-within-a-python-script.html

Mais ça ne me semble pas une bonne idée, si vraiment tu veux lister les dépendances de ton fichier dans ton fichier tu peux plutôt utiliser la PEP 723, que je n’ai pas testé encore (c’est tout frais).

1 « J'aime »

Ensuite, le mot-clé import n’attend pas une expression Python mais un nom, qui sera utilisé comme nom de module à importer. On écrit import sys et par import 'sys'.

Si le nom du module à importer est référencé par une chaîne de caractères, tu peux utiliser importlib pour l’importer.
Par exemple :

>>> import importlib
>>> mod = importlib.import_module('sys')
>>> mod.version_info
sys.version_info(major=3, minor=11, micro=6, releaselevel='final', serial=0)
1 « J'aime »

Bonjour,

Ca me fait penser a un PEP qui a récemment été accepte et qui propose ce syntaxe pour specifier les dépendances d’un script… ca oblige d’avoir un outil lanceur pour gérer l’installation…

# /// script
# requires-python = ">=3.11"
# dependencies = [
#   "requests<3",
#   "rich",
# ]
# ///

import requests
from rich.pretty import pprint

resp = requests.get("https://peps.python.org/api/peps.json")
data = resp.json()
pprint([(k, v["title"]) for k, v in data.items()][:10])
1 « J'aime »

Bonjour,

Sur vos conseils, j’ai commencé avec importlib.import_module().
Ca me pose un problème et je dois approfondir le sujet.

Ceci dit je me pose trop de problèmes pour pas grand chose.

Merci pour vos contributions.

pierre estrem

J’aimerais compléter avec un dernier truc parce que personne ne l’a encore évoqué : exec('import module_name').

Cela dit, je soutiens cependant que la méthode recommandée est de passer par importlib.import_module('module_name').

Bonjour,

Eh bien merci, je crois que ça le fait avec ‘exec’ et on peut alors
importer depuis une boucle et f-string :
Ceci marche :

for mod in ['pyxhook','tkinter']:
    try:
        exec(f'from {mod} import *')
    except ImportError:
        # Traitement

pierre estrem

Si tu te sens encore d’attaque, je te mets au défi de coder ce qu’il faut pour pouvoir gérer l’import de n’importe lequel des cas génériques suivants :

import mod.ou.submod                      # import itertools
import mod.ou.submod as alias             # import numpy as np
from mod.ou.submod import machin          # from torchtyping import TensorType
from mod.ou.submod import machin as alias # from sphinx.domains.c import CObject as Base_CObject
from mod.ou.submod import machin, truc    # from typing import List, Tuple

Disclaimer : Mon «agenda caché» est de

  • te pousser dans tes retranchements, te faire réaliser les limites de la simple liste ['module1', 'module2'] et te faire aller au-delà ;
  • également (et idéalement) te faire abandonner l’usage de l’astérisque — qu’on sait être sujet à des effets de bord potentiellement risqués ;
  • et, enfin, te faire réfléchir à comment organiser et optimiser ton code afin qu’il gère d’une traite (a) les différents cas d’import et (b) les installations là où elles sont nécessaires, le tout dans le bon ordre, algorithmiquement parlant.

Bonne chance !

Quel est l’intérêt de passer par exec pour ça ?
importlib répond très bien au besoin et ne cause pas tous les problèmes qu’il peut y avoir avec exec (exécution de code arbitraire notamment).

Merci d’avoir complété ma réponse.

L’intérêt ? Voyons. D’un, c’est l’entraide (comme le dit l’un des badges apposés à cette discussion) et de deux, la production d’un contenu informatif de qualité. Ce qui, selon ma définition, consiste à

  • (a) apporter des réponses pertinentes et complètes (en aucun cas ne taire une info, surtout pas celle qui est par ailleurs librement accessible),
  • (b) insérer des liens vers des sources pertinentes et de qualité,
  • (c) mentionner les éventuelles mises en garde et précautions à prendre,
  • (d) compléter ou corriger les réponses des autres.

Bonsoir le Monde libre,

Je suis reconnaissant à vos contributions qui m’apprennent des choses et
me mettent aussi en garde.

Donc si on doit reprocher quelque chose à quelqu’un, c’est à moi.

Oui je suis relativement newbie en Python.

Le fait est que j’essais de coder pour aider des membres d’une
association qui peuvent rencontrer des erreurs lors de l’exécution de
scripts et étant donné qu’ils sont très “éloignés” de l’informatique je
souhaite éviter qu’ils rencontrent des erreurs, d’où mon intérêt à gérer
une exception ImportError.
Leurs machines ne sont pas exactement configurées comme la mienne.

Amicalement vôtre

Bonsoir,

Merci pour cette invitation. :wink:

Je vais m’en tenir aux modules dont j’ai strictement besoin, car je
serai bien en mal de relever votre challenge. :wink:

pierre estrem