0

I have project that I decided to divide into subfolders. My main module main.py imports other module mod1.py from a subfolder. The imported module mod1.py uses images that are located in another subfolder and refers to them relatively. I can't use absolute path from the drive, but I know the relative path from the beginning of the project structure.

The situation is illustrated below somehow

project
├── main.py
└───subfolder
     ├───mod1.py
     └───pictures
          └───pic1.png

So there's a line in mod1.py:

image = Image.open("./pictures/pic1.png")

and when I import mod1.py in main.py and run the program I get an error:

FileNotFoundError: [Errno 2] No such file or directory: './pictures/pic1.png'

How to access those pictures when I run main.py and import a module that relatively refers to them?

I have __init__.py file in the subfolder and all the imports are working.

Lolman
  • 107
  • 8

2 Answers2

0

try this

try:
    image = Image.open("pictures/pic1.png")
except FileNotFoundError:
    image = Image.open("subfolder/pictures/pic1.png")

so python will try the first path, if it fails, it will try the second, which looks for the main.py file

  • The whole project is much larger, I might run into this problem 2-3 times and would need to make as many try - except pairs for it. It should work, but I'm looking to learn a proper way to do this. – Lolman Aug 30 '21 at 19:18
  • Please add further details to expand on your answer, such as working code or documentation citations. – Community Aug 30 '21 at 20:25
0

While Jorge's answer may work in some cases I suggest understanding why yours does not work and look how other people have solved this problem. Lets take a very simple example.

project
  dir1
    test.py
    dir2
      test2.py

Lets assume the full path to my project directory is located at /Users/sstacha/tmp/test_python/ and my 2 test files contain the following

test.py

import os
from pathlib import Path

from dir2.test2 import function2

def function1():
    path = os.getcwd()
    print(f"function1.os.cwd(): {path}")

    DIR = Path(__file__).resolve()
    print(f"function1.pathlib_path: {DIR}")

function1()
function2()

test2.py

import os
from pathlib import Path

def function2():
    path = os.getcwd()
    print(f"function2.os.cwd(): {path}")

    DIR = Path(__file__).resolve()
    print(f"function2.pathlib_path: {DIR}")

if i execute python dir1/test.py from the project directory I get the following output:

$ python dir1/test.py
function1.os.cwd(): /Users/sstacha/tmp/test_python
function1.pathlib_path: /Users/sstacha/tmp/test_python/dir1/test.py
function2.os.cwd(): /Users/sstacha/tmp/test_python
function2.pathlib_path: /Users/sstacha/tmp/test_python/dir1/dir2/test2.py

if I instead cd to dir1 and execute python test.py I get this output:

$ python test.py
function1.os.cwd(): /Users/sstacha/tmp/test_python/dir1
function1.pathlib_path: /Users/sstacha/tmp/test_python/dir1/test.py
function2.os.cwd(): /Users/sstacha/tmp/test_python/dir1
function2.pathlib_path: /Users/sstacha/tmp/test_python/dir1/dir2/test2.py

So your actual problem is that os.cwd() will always be set to whatever directory the os was set to when the python command was run. I also included a line from how the Django settings file handles this issue for python >= 3.4. As you can see, this approach will be relative to whatever file your function is defined in which should be a better / more portable solution regardless of what directory the python executable is called from.

Hopefully that helps you understand your issue better and a possible solution that might work for you.

I realized I never really fully answered the question here would be an example:

DIR = Path(__file__).resolve().parent
image = Image.open(DIR+"/pictures/pic1.png")

By the way if you are using a version earlier than 3.4 this is how the Django settings file approached it:

DIR = os.path.dirname(os.path.abspath(__file__))
image = Image.open(DIR+"/pictures/pic1.png")

Steve Stacha
  • 178
  • 2
  • 8