0

I am trying to import a module given an absolute path. I have read through some posts and I chose to follow one method mentioned in https://stackoverflow.com/a/53311583/19947267 but for some reason it doesnt work; below is my directory. my example directory looks like this:

<root>
 |
 +- /std1
 |   |
 |   +- main.py
 |
 +- /std2
 |   |
 |   +- lib.py

I cd to /std1 and now I want to import a module from lib.py, but when I implement the following code:

import sys 
import os
configfile = '~/std2/'
sys.path.append(os.path.dirname(os.path.expanduser(configfile)))
from std2.lib import target_module

It cant seem to recognise std2.lib, the error message was

ModuleNotFoundError: No module named 'std2.lib'

is there something I did wrong here? Can anyone please help?

  • 1. You said "" but use `~` (user directory) - which is it? 2. If it's always one directory back from std1, you could play with pathlib and `__file__` to just get current file's path, then parent (std1), then its parent () and append that to PATH. – h4z3 Aug 04 '23 at 07:07
  • this is almost never the right way to do things. Anyway, did you try adding an `__init__.py`? – juanpa.arrivillaga Aug 04 '23 at 07:11

2 Answers2

0

Messing with sys.path is almost never the right way to do this. If you must though, then you need to understand that if you append ~/std2/ to the search path, it won't be able to find the name std2, because the import system searches inside of std2. And that is what your code does, your approach wasn't working because of this behavior of os.path.dirname when the string has a leading forward slash:

>>> os.path.dirname(os.path.expanduser('~/std2/'))
'/Users/juan/std2'
>>> os.path.dirname(os.path.expanduser('~/std2'))
'/Users/juan'

So, the simplest fix is:

import sys 
import os
configfile = '~/std2' # NOTE NO TRAILING FORWARD SLASH
sys.path.append(os.path.dirname(os.path.expanduser(configfile)))
import std2.lib

Or instead, you can change your import statement to use just lib, so:

import sys 
import os
configfile = '~/std2/'
sys.path.append(os.path.dirname(os.path.expanduser(configfile)))
import lib

Better yet, you should use pathlib instead of os.path:

import sys
import pathlib
configfile = pathlib.Path("~/std2/")
sys.path.append(str(configfile.expanduser()))
import lib

But if you wanted to be able to import std2, you could add the parent directory to the path:

import sys
import pathlib
configfile = pathlib.Path("~/std2/")
sys.path.append(str(configfile.expanduser().parent))
import std2.lib

(See how much nicer pathlib is?)

But I really must reiterate, you almost certainly shouldn't be messing with sys.path to begin with.

juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
0

You could try creating an empty file called init.py in std2 and append the root directory to the Pythonpath (explained here)

LarsJaeger
  • 100
  • 7