What would be the practical benefit of being able to import those modules, rather than simply renaming them to use valid Python names so they can be imported normally? These are really quite special cases and relatively easy to fix, and in general, you really shouldn’t be doing this in the first place unless you really need it, because it makes your code more complex, harder to understand and non-portable.
The first case can, of course, be imported via import a
, or 62.5% fewer characters and greater clarity.
In the second and third case, it isn’t obvious what name the module should be mapped to. In the first, an absolute path is given, which begs the question of whether you just want to use the final path component as the module name, or if not, where along the path do you want to consider the top-level package directory. In the second, the import doesn’t work currently because the package .a
is not a valid Python package name; thus, it is not obvious what import "a/b.py"
should map to in the namespace.
However, you can already handle either case via importlib:
spec = importlib.util.spec_from_file_location("b", "./a/b.py")
module = importlib.util.module_from_spec(spec)
sys.modules["b"] = module
spec.loader.exec_module(module)
That’s rather more verbose, but its a special case, and there’s an issue to make it a simpler, and you can easily make it a utility function, i…e.
def import_path(path, name=None):
if name is None:
name = Path(path).stem
spec = importlib.util.spec_from_file_location(name, path)
module = importlib.util.module_from_spec(spec)
sys.modules[name] = module
spec.loader.exec_module(module)
return module
which you could call as
import_path("E:/a/b.py")
import_path(".a/b.py")
import_path(".b.py", "b")
But again, you should understand and justify why specifically you need this instead of relying on standard import semantics.