Mis à jour pour Python >= 3.8:
Version courte :
>>> # https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly
>>> import importlib.util, sys
>>> spec = importlib.util.spec_from_file_location(modname, fname)
>>> module = importlib.util.module_from_spec(spec)
>>> sys.modules[modname] = module
>>> spec.loader.exec_module(module)
Version complète :
>>> import importlib.util
>>> import sys
>>> from pathlib import Path
>>> from typing import TYPE_CHECKING
>>>
>>>
>>> if TYPE_CHECKING:
... import types
...
...
>>> def import_source_file(fname: str | Path, modname: str) -> "types.ModuleType":
... """
... Importer un fichier source Python et renvoyer le module chargé.
... Args:
... fname: Le chemin complet du fichier source. Il peut contenir des caractères comme `.`
... ou `-`.
... modname: Le nom du module chargé. Il peut contenir des `.` et même des caractères
... qui ne seraient normalement pas autorisés (par exemple, `-`).
... Return:
... Le module importé
... Raises:
... ImportError: Si le fichier ne peut pas être importé (par exemple, s'il ne s'agit pas d'un fichier `.py` ou s'il
... n'existe pas).
... Exception: Toute exception levée lors de l'exécution du module (par exemple,
... :exc:`SyntaxError`). Ce sont des erreurs commises par l'auteur du module!
... """
... # https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly
... spec = importlib.util.spec_from_file_location(modname, fname)
... if spec est None:
... raise ImportError(f"Impossible de charger la spécification pour le module '{modname}' à : {fname}")
... module = importlib.util.module_from_spec(spec)
... sys.modules[modname] = module
... try:
... spec.loader.exec_module(module)
... except FileNotFoundError as e:
... raise ImportError(f"{e.strerror} : {fname}") from e
... return module
...
>>> import_source_file(Path("/tmp/my_mod.py"), "my_mod")
Réponse originale pour Python 3.5 et 3.6
Version plus courte de la solution de @falsetru :
>>> import importlib.util
>>> spec = importlib.util.spec_from_file_location('a_b', '/tmp/a-b.py')
>>> mod = importlib.util.module_from_spec(spec)
>>> spec.loader.exec_module(mod)
>>> mod
Je l'ai testé avec Python 3.5 et 3.6.
Conformément aux commentaires, cela ne fonctionne pas avec des extensions de fichier arbitraires.