30

There are two directories on my desktop, DIR1 and DIR2 which contain the following files:

DIR1:
file1.py

DIR2:
file2.py  myfile.txt

The files contain the following:

file1.py

import sys

sys.path.append('.')
sys.path.append('../DIR2')

import file2

file2.py

import sys

sys.path.append( '.' )
sys.path.append( '../DIR2' )

MY_FILE = "myfile.txt"

myfile = open(MY_FILE)

myfile.txt

some text

Now, there are two scenarios. The first works, the second gives an error.

Scenario 1

I cd into DIR2 and run file2.py and it runs no problem.

Scenario 2

I cd into DIR1 and run file1.py and it throws an error:

Traceback (most recent call last):
  File "<absolute-path>/DIR1/file1.py", line 6, in <module>
    import file2
  File "../DIR2/file2.py", line 9, in <module>
    myfile = open(MY_FILE)
IOError: [Errno 2] No such file or directory: 'myfile.txt'

However, this doesn't make any sense to me, since I have appended the path to file1.py using the command sys.path.append('../DIR2').

Why does this happen when file1.py, when file2.py is in the same directory as myfile.txt yet it throws an error?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
makansij
  • 9,303
  • 37
  • 105
  • 183
  • 9
    Python's `sys.path` only affects how Python looks for modules. If you want to `open` a file, `sys.path` is not involved. Your `open` is failing because you're not running the script from the directory that contains `myfile.txt`. – larsks Aug 27 '15 at 01:46
  • Okay, thanks @larsks. But, how do I affect how python opens files? i.e. how do I allow it to open files from a different directory? – makansij Aug 27 '15 at 01:51
  • @Hunle use the complete relative path to that file , or best use absolute path if possible. – Anand S Kumar Aug 27 '15 at 01:52
  • Can't use absolute path. This is a shared application. Okay, thank you. – makansij Aug 27 '15 at 01:52
  • Still....I'm confused. `myfile.txt` is in the same directory as the file trying to open it `file2.py`. And, like I said, if I just run `file2.py` alone it works fine. – makansij Aug 27 '15 at 01:57
  • 1
    You never showed us how you are running the files. If you're changing into `DIR2` before running `file2` that would explain the behavior you are seeing. If you're doing anything else, show us the *exact* steps. – larsks Aug 27 '15 at 01:59
  • similar question ----> [http://stackoverflow.com/questions/714063/python-importing-modules-from-parent-folder][1] let me know if it helps. [1]: http://stackoverflow.com/questions/714063/python-importing-modules-from-parent-folder – Stef g Aug 27 '15 at 02:05
  • 2
    The title of this question is misleading, since it's about `open`, not `import`. People searching on Google for how to import using `sys.path.append()` will find this post a waste of time - and that's where most of the traffic is probably coming from. – JoseOrtiz3 Dec 09 '21 at 21:37
  • sorry about that. suggest an edit to address this issue. – makansij Dec 09 '21 at 22:54

2 Answers2

19

You can create a path relative to a module by using a module's __file__ attribute. For example:

myfile = open(os.path.join(
    os.path.dirname(__file__),
    MY_FILE))

This should do what you want regardless of where you start your script.

larsks
  • 277,717
  • 41
  • 399
  • 399
  • 1
    I would start by printing out the value of the path (`thepath = os.path.join( os.path.dirname(__file__)+'/..//', JSON_FILE)`) and seeing if it looks sane. I'm suspicious that we're dealing with an [XY problem](http://www.perlmonks.org/?node=XY+Problem) here, because it's not clear from your question exactly why you're trying to access files like this. – larsks Aug 31 '15 at 19:59
  • I figured it out. Thanks for your help. – makansij Aug 31 '15 at 21:51
5

Replace

MY_FILE = "myfile.txt"
myfile = open(MY_FILE)

with

MY_FILE = os.path.join("DIR2", "myfile.txt")
myfile = open(MY_FILE)

That's what the comments your question has are referring to as the relative path solution. This assumes that you're running it from the directory one up from myfile.txt... so it is not ideal.

If you know that my_file.txt is always going to be in the same directory as file2.py then you can try something like this in file2...

from os import path

fname =  path.abspath(path.join(path.dirname(__file__), "my_file.txt"))
myfile = open(fname)
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
demented hedgehog
  • 7,007
  • 4
  • 42
  • 49
  • Can I suggest that you put a print(\_\_file\_\_ + " " + os.getcwd()) call in each of your files .. I think you may have a broken understanding of how the paths are resolved. – demented hedgehog Aug 27 '15 at 02:13