1

I have 2 files:

  1. First file test1.py:

    from dir2.test2 import func2
    
    def func1():
       with open("test1.txt", "w") as f:
           f.write("some text")
    
    func1()
    func2()
    
  2. Second file test2.py:

    def func2():
        with open("test2.txt", "w") as f:
            f.write("some text")
    

And my directory structure looks like this before running test1.py:

dir1
 |
 - test1.py
 |
 - dir2
    |
    - test2.py

After running the test1.py the directory structure look like this:

dir1
 |
 - test1.txt
 | 
 - test2.txt
 |
 - test1.py
 |
 - dir2
    |
    - test2.py

But after running the script I was expecting the directory structure to look like this:

dir1
 |
 - test1.txt
 |
 - test1.py
 |
 - dir2
    | 
    - test2.txt
    |
    - test2.py

I have tried searching ways to fix this but haven't found any.

So is there anyway to get something like I was expecting after running test1.py.

abhigyanj
  • 2,355
  • 2
  • 9
  • 29
  • You need to handle the path yourself. Look at https://stackoverflow.com/questions/32470543/open-file-in-another-directory-python – kumarchandresh Nov 23 '20 at 05:37
  • @chandr3sh Since my code is being deployed on a different server on Heroku, I cannot get the full path – abhigyanj Nov 23 '20 at 05:38
  • The path is all relative (as per your code) and depends on where you are running the script from. In **"test2.py"**, you may want to specify the path as `./dir2/test2.txt` considering that you are running the script from within `dir1` – Melvin Abraham Nov 23 '20 at 05:39
  • When you first run the script from __main__, it frames you in a specific location - the current working directory. You may be calling test1.py like so: `python /home/dev/dir1/test1.py` or `C:\Users\You\dev\dir1\test1.py`. Python takes in func2 and reads the relative path in the open() call relative to the current working directory (test1.py). This is why it saves the test2.txt file in dir1, not dir2. – PeptideWitch Nov 23 '20 at 05:40
  • @PeptideWitch So how shall can I fix it? – abhigyanj Nov 23 '20 at 05:41

1 Answers1

2

Relative file paths like "test1.txt" are relative to the directory you run the script from. Since, you run test1.py from the same directory as itself - the relative path is resolved to the same directory as well. So test1.txt becomes /path/to/dir1/test1.txt

If you ran test1.py from within dir2, you'd see both text files in /path/to/dir2/.

This is how relative paths work in pretty much every language. If you want reliable path building, use os.path functions

cwd = os.path.dirname(os.path.abspath(__file__))

This will give you an absolute path to the file you use this on. So if you use this on test1.py - you get /path/to/dir1. Now you can use os.path.join to build your desired paths

Just for a complete example, to make test2.txt inside dir2 (which is inside dir1), assuming that cwd line is resolved in test1.py (i.e __file__ points to test1.py) you simply do

test2_path = os.path.join(cwd, 'dir2', 'test2.txt')
with open(test2_path, 'w') as f:
    ....

And, if cwd is resolved in test2.py (__file__ points to test2.py), you do

test2_path = os.path.join(cwd, 'test2.txt')
Chase
  • 5,315
  • 2
  • 15
  • 41
  • Thanks for the detailed explanation, but what shall my code look like with `cwd = os.path.dirname(os.path.abspath(__file__))` implemented? – abhigyanj Nov 23 '20 at 05:42
  • `cwd` stands for *current working directory*, by the way - this is a useful way to think about where code is being called and where relative paths point from – PeptideWitch Nov 23 '20 at 05:44
  • 1
    @AbhigyanJaiswal As I said, `cwd` is path to the file you call it in. You can now use `os.path.join(cwd, 'dir2')` to get `/path/to/dir1/dir2`, which you can use in `open` – Chase Nov 23 '20 at 05:45
  • `os.getcwd()` could also work assuming the code always starts off from test1.py as the main call. – PeptideWitch Nov 23 '20 at 05:46
  • @AbhigyanJaiswal I explicitly mentioned you need to join with `dir2` if `__file__` is resolved in `test1.py`, but you put it in `test2.py`. Please read on how `os.path.dirname` works - if you do `os.path.dirname(os.path.abspath(__file__))` on `test2.py`, it returns `/path/to/dir1/dir2`. So you should be doing `os.path.join(cwd, 'test2.txt')` – Chase Nov 23 '20 at 05:52