It seems there are already quite some questions here about relative import in python 3, but after going through many of them I still didn\'t find the answer for my issue. s
None of these solutions worked for me in 3.6, with a folder structure like:
package1/
subpackage1/
module1.py
package2/
subpackage2/
module2.py
My goal was to import from module1 into module2. What finally worked for me was, oddly enough:
import sys
sys.path.append(".")
Note the single dot as opposed to the two-dot solutions mentioned so far.
Edit: The following helped clarify this for me:
import os
print (os.getcwd())
In my case, the working directory was (unexpectedly) the root of the project.
from package.A import foo
I think it's clearer than
import sys
sys.path.append("..")
In my case, I had to change to this: Solution 1(more better which depend on current py file path. Easy to deploy) Use pathlib.Path.parents make code cleaner
import sys
import os
import pathlib
target_path = pathlib.Path(os.path.abspath(__file__)).parents[3]
sys.path.append(target_path)
from utils import MultiFileAllowed
Solution 2
import sys
import os
sys.path.append(os.getcwd())
from utils import MultiFileAllowed
import sys
sys.path.append("..") # Adds higher directory to python modules path.
Try this. Worked for me.
This one didn't work for me as I'm using Django 2.1.3:
import sys
sys.path.append("..") # Adds higher directory to python modules path.
I opted for a custom solution where I added a command to the server startup script to copy my shared script into the django 'app' that needed the shared python script. It's not ideal but as I'm only developing a personal website, it fit the bill for me. I will post here again if I can find the django way of sharing code between Django Apps within a single website.
As the most popular answer suggests, basically its because your PYTHONPATH
or sys.path
includes .
but not your path to your package. And the relative import is relative to your current working directory, not the file where the import happens; oddly.
You could fix this by first changing your relative import to absolute and then either starting it with:
PYTHONPATH=/path/to/package python -m test_A.test
OR forcing the python path when called this way, because:
With python -m test_A.test
you're executing test_A/test.py
with __name__ == '__main__'
and __file__ == '/absolute/path/to/test_A/test.py'
That means that in test.py
you could use your absolute import
semi-protected in the main case condition and also do some one-time Python path manipulation:
from os import path
…
def main():
…
if __name__ == '__main__':
import sys
sys.path.append(path.join(path.dirname(__file__), '..'))
from A import foo
exit(main())