Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python3 importlib.util.spec_from_file_location with relative path?

Tags:

python

There are a lot of python questions about how to import relative packages or by explicit location (linked to two popular examples).

In addition there is always the documentation

Having read this, I am still not quite sure what specs are, how they are related to modules, and why one would need to tokenize it.

So for someone who doesn't understand, could you please try to explain how one would do this (programmatically and what the means under the hood)

e.g.

if I have

proj-dir
--mod1
--|--__init__.py
--|--class1.py
--mod2
--|--__init__.py
--|--class2.py

how do I import mod2 into mod1?

import sys
sys.path.insert(0, "../mod2")

this technically works, but I fear that it may cause issues in the future if I try to pickle objects and use them elsewhere...

The explicit location suggested

import importlib.util
spec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py")
foo = importlib.util.module_from_spec(spec)
spec.loader.exec_module(foo)
foo.MyClass()

so in this case I just do:

import importlib.util
spec = importlib.util.spec_from_file_location("mod2.class2", "../mod2/class2.py")
foo = importlib.util.module_from_spec(spec)
spec.loader.exec_module(foo)
foo.MyClass()

??

like image 303
SumNeuron Avatar asked Feb 17 '18 12:02

SumNeuron


1 Answers

First of all, let me clarify the differences between a Python module & a Python package so that both of us are on the same page. ✌


###A module is a single .py file (or files) that are imported under one import and used. ✔
`import aModuleName

Here 'aModuleName' is just a regular .py file.`

###Whereas, a package is a collection of modules in directories that give a package hierarchy. A package contains a distinct __init__.py file. ✔

 # Here 'aPackageName` is a folder with a `__init__.py` file
 # and 'aModuleName', which is just a regular .py file.

Therefore, the correct version of your proj-dir would be something like this, ⤵

 proj-dir
 ├── __init__.py
 ├── package1
 │   ├── __init__.py
 │   ├── module1.py
 └── package2
     ├── __init__.py
     └── module2.py 

🔎 Notice that I've also added an empty __init__.py into the proj-dir itself which makes it a package too.

👍 Now, if you want to import any python object from module2 of package2 into module1 of package1, then the import statement in the file module1.py would be

from proj-dir.package2.module2 import object2
# if you were to import the entire module2 then,
from proj-dir.package2 import module2
like image 136
Sushant Chaudhary Avatar answered Oct 18 '22 15:10

Sushant Chaudhary