0

I have this code in my_program.py:

from my_module import do_stuff_with_file

do_stuff_with_file("hi.txt")

And this is my_module.py:

def do_stuff_with_file(fileName):
    print(fileName)
    # do stuff with the file

A file not found error arises when my_module.py is not in the same directory as my_program.py. This problem was solved using this code (my_module.py).

def do_stuff_with_file(fileName):
    fileName = os.path.join(os.path.dirname(sys.modules['__main__'].__file__), fileName)
    print(fileName)
    # do stuff with file

The issue arises when my_program.py is imported by a file in a different directory.

How can I fix this?

7
  • The problem is not clear. Could you restate the observed behavior and the desired output ? Commented Jun 16, 2021 at 13:31
  • @Lenormju, I have tried to clarify the problem :). If you need an example, look at github.com/kethan1/playsound2, and run the tests with pytest Commented Jun 16, 2021 at 15:36
  • Is this a file that is delivered with your project is and supposed to be relative to the module, or should this code work with any file anywhere? Since my_program.py used a relative path name, its relative to whatever os.getcwd() says is the current path. If you run from the command line, its the shells current directory. Otherwise its..., well, who knows? Commented Jun 16, 2021 at 23:09
  • Its weird that do_stuff_with_file would try to fix a relative path name. Shouldn't it work with anything? Likely you want any path manipulation in my_program.py. We need to know where you expect this file to be. Commented Jun 16, 2021 at 23:10
  • @tdelaney the my_module.py might be in a subdirectory or parent directory of my_program.py. Fixing the path fixes this (using sys.modules['__main__'].__file__). When running with pytest for example (or importing my_program.py from another python file), the issue occurs. Commented Jun 17, 2021 at 0:12

1 Answer 1

1

Given the following file hierarchy :

stack_overflow/
├─ q67993523/
   ├─ my_module/
   │  ├─ __init__.py
   ├─ 67993523.py
   ├─ hi.txt

With the following file content :

# 67993523.py
from my_module import do_stuff_with_file

do_stuff_with_file("hi.txt")
# my_module/__init__.py
def do_stuff_with_file(filename):
    print(f"{filename!s} content is :")
    with open(filename, "rt") as file:
        print(file.read())

and the file hi.txt :

Hello !

When I run C:\path\to\python.exe C:/stack_overflow/q67993523/67993523.py (with the path to q67993523 included in my PYTHONPATH), with my current directory being q67993523/, I get :

hi.txt content is :
Hello !

But if I change my current dir to q67993523/my_module/ and execute the exact same command, I get :

hi.txt content is :
Traceback:
[...]
FileNotFoundError: [Errno 2] No such file or directory: 'hi.txt'

because relative to the current working directory q67993523/my_module/ there is no file hi.txt, the file would be ../hi.txt.

I think what you are doing is an instance of the XY problem.

What you are trying to achieve is to find a file given its name but not the location. It is very difficult to do, prone to error, and would include lots of hacks to work.
I don't think it is actually what you want to do. What you want to do, I presume, is not to search for files but just to use them. So you should not lose the precious information of their location.

For example, in your main script (mine is 67993523.py), you know that the file is right there, in the same directory. But if you just send hi.txt, because the function don't know the file location of the code that called her, it does not know where to search for the file.
Instead, give the complete file location, namely the absolute path.

If I change my main script to :

# 67993523.py
from pathlib import Path

from my_module import do_stuff_with_file

the_directory_of_this_pyfile = Path(__file__).parent
do_stuff_with_file((the_directory_of_this_pyfile / "hi.txt").absolute())

And run it with my current directory being q67993523/, I get :

C:\stack_overflow\q67993523\hi.txt content is :
Hello !

And when I change my current directory to q67993523/my_module/, I get the same thing :

C:\stack_overflow\q67993523\hi.txt content is :
Hello !

The difference is that in your script, the hi.txt filename assumes that your current working directory is q67993523/. If you have a different current working directory (because Pytest, because running the script for anywhere you want, ... see the comment from @tdelaney) then there is no ./hi.txt file, so it will fail.

I encourage you to learn on the topic of current working directory and how to express the current Python file directory.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks so much for your help. I knew I probably couldn't get away with a relative path, but using pathlib seems to work. Thanks!
@KetZoomer the main thing to understand is the relation between the current working directory which is the start of relative paths, and absolute paths (which start at the root of the drive). Relative paths are shorter, but cause problems when the cwd is not under full control. Hence I tend to favor absolute paths, which work in every case.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.