Open file in a relative location in Python

647,847

Solution 1

With this type of thing you need to be careful what your actual working directory is. For example, you may not run the script from the directory the file is in. In this case, you can't just use a relative path by itself.

If you are sure the file you want is in a subdirectory beneath where the script is actually located, you can use __file__ to help you out here. __file__ is the full path to where the script you are running is located.

So you can fiddle with something like this:

import os
script_dir = os.path.dirname(__file__) #<-- absolute dir the script is in
rel_path = "2091/data.txt"
abs_file_path = os.path.join(script_dir, rel_path)

Solution 2

This code works fine:

import os


def readFile(filename):
    filehandle = open(filename)
    print filehandle.read()
    filehandle.close()



fileDir = os.path.dirname(os.path.realpath('__file__'))
print fileDir

#For accessing the file in the same folder
filename = "same.txt"
readFile(filename)

#For accessing the file in a folder contained in the current folder
filename = os.path.join(fileDir, 'Folder1.1/same.txt')
readFile(filename)

#For accessing the file in the parent folder of the current folder
filename = os.path.join(fileDir, '../same.txt')
readFile(filename)

#For accessing the file inside a sibling folder.
filename = os.path.join(fileDir, '../Folder2/same.txt')
filename = os.path.abspath(os.path.realpath(filename))
print filename
readFile(filename)

Solution 3

I created an account just so I could clarify a discrepancy I think I found in Russ's original response.

For reference, his original answer was:

import os
script_dir = os.path.dirname(__file__)
rel_path = "2091/data.txt"
abs_file_path = os.path.join(script_dir, rel_path)

This is a great answer because it is trying to dynamically creates an absolute system path to the desired file.

Cory Mawhorter noticed that __file__ is a relative path (it is as well on my system) and suggested using os.path.abspath(__file__). os.path.abspath, however, returns the absolute path of your current script (i.e. /path/to/dir/foobar.py)

To use this method (and how I eventually got it working) you have to remove the script name from the end of the path:

import os
script_path = os.path.abspath(__file__) # i.e. /path/to/dir/foobar.py
script_dir = os.path.split(script_path)[0] #i.e. /path/to/dir/
rel_path = "2091/data.txt"
abs_file_path = os.path.join(script_dir, rel_path)

The resulting abs_file_path (in this example) becomes: /path/to/dir/2091/data.txt

Solution 4

It depends on what operating system you're using. If you want a solution that is compatible with both Windows and *nix something like:

from os import path

file_path = path.relpath("2091/data.txt")
with open(file_path) as f:
    <do stuff>

should work fine.

The path module is able to format a path for whatever operating system it's running on. Also, python handles relative paths just fine, so long as you have correct permissions.

Edit:

As mentioned by kindall in the comments, python can convert between unix-style and windows-style paths anyway, so even simpler code will work:

with open("2091/data/txt") as f:
    <do stuff>

That being said, the path module still has some useful functions.

Solution 5

I spend a lot time to discover why my code could not find my file running Python 3 on the Windows system. So I added . before / and everything worked fine:

import os

script_dir = os.path.dirname(__file__)
file_path = os.path.join(script_dir, './output03.txt')
print(file_path)
fptr = open(file_path, 'w')
Share:
647,847

Related videos on Youtube

Neuron
Author by

Neuron

We're made of star stuff. We are a way for the cosmos to know itself. he/him

Updated on February 16, 2022

Comments

  • Neuron
    Neuron over 2 years

    Suppose my python code is executed a directory called main and the application needs to access main/2091/data.txt.

    how should I use open(location)? what should the parameter location be?

    I found that below simple code will work.. does it have any disadvantages?

    file = "\2091\sample.txt"
    path = os.getcwd()+file
    fp = open(path, 'r+');
    
    • orip
      orip almost 13 years
      You're using unescaped backslashes. That's one disadvantage.
    • Russ
      Russ almost 13 years
      Several disadvantages. 1) As per @orip, use forward slashes for paths, even on windows. Your string won't work. Or use raw strings like r"\2091\sample.txt". Or escape them like "\\2091\\sample.txt" (but that is annoying). Also, 2) you are using getcwd() which is the path you were in when you execute the script. I thought you wanted relative to the script location (but now am wondering). And 3), always use os.path functions for manipulating paths. Your path joining line should be os.path.join(os.getcwd(), file) 4) the ; is pointless
    • Russ
      Russ almost 13 years
      And for good measure... 5) use context guards to keep it clean and avoid forgetting to close your file: with open(path, 'r+') as fp:. See here for the best explanation of with statements I've seen.
    • OPMendeavor
      OPMendeavor over 4 years
      beside the necessary care on slashes, as just indicated, there is the function os.path.abspath to get easly the full path of the relative path to open. final statement looks like this: os.path.abspath('./2091/sample.txt')
  • kindall
    kindall almost 13 years
    relpath() converts a pathname to a relative path. Since it's already a relative path, it will do nothing.
  • Wilduck
    Wilduck almost 13 years
    It will convert it from a unix-style path to windows-style path if appropriate. Is there another function in the os.path module that would be a better choice?
  • kindall
    kindall almost 13 years
    Windows will already work fine with a UNIX-style path. At least the NT-based series will (2000, XP, Vista, 7). No conversion is necessary.
  • Russ
    Russ almost 13 years
    Not true... the working directory inside a script is the location you ran the script from, not the location of the script. If you run the script from elsewhere (maybe the script is in your system path) the relative path to the subdirectory will not work. Please see my answer on how to get around this.
  • Russ
    Russ almost 13 years
    This answer is not quite correct and will cause problems. Relative paths are by default relative to the current working directory (path the script was executed from), and NOT the actual script location. You need to use __file__. Please see my answer.
  • Admin
    Admin almost 13 years
    I found that below simple code will work..does it have any disadvantages ? <pre> file="\sample.txt" path=os.getcwd()+str(loc)+file fp=open(path,'r+');<code>
  • orip
    orip almost 13 years
    @Russ - the OP's example uses getcwd(). I read the original description as "relative to where I run the script, regardless of where the code sits".
  • Russ
    Russ almost 13 years
    @orip - the OP added the getcwd() call 3 hrs after the question. No matter... moving on. :)
  • Cory Mawhorter
    Cory Mawhorter almost 11 years
    @Arash The disadvantage to that is the cwd (current working directory) can be anything, and won't necessarily be where your script is located.
  • Cory Mawhorter
    Cory Mawhorter almost 11 years
    __file__ is a relative path (at least on my setup, for some reason), and you need to call os.path.abspath(__file__) first. osx/homebrew 2.7
  • Luke Taylor
    Luke Taylor over 8 years
    You could even combine both approaches for the simpler os.path.dirname(os.path.abspath(__file__))
  • Grant Hulegaard
    Grant Hulegaard over 8 years
    @LukeTaylor Indeed that would be better than trying to replicate the os.path.dirname functionality yourself as I did in my answer last year.
  • foobarbecue
    foobarbecue about 8 years
    Did the author of this answer confuse os.path.relpath with os.path.abspath?
  • Soumendra
    Soumendra almost 8 years
    os.path.dirname(file) is not working for me in Python 2.7. It is showing NameError: name '__file__' is not defined
  • Enkum
    Enkum over 5 years
    @Soumendra I think you are trying it in the console. Try it in a *.py file.
  • M. Paul
    M. Paul over 5 years
    For me accessing the file in the parent folder of the current folder did not worked..the .. is added as string..
  • Mr_and_Mrs_D
    Mr_and_Mrs_D about 5 years
    Instead of path = "/".join(script_directory) + "/" + rel_path you should use the os module as in path = os.path.join(script_directory, rel_path). Instead of manually parsing the path you should be using script_path = os.path.dirname(__file__)
  • Mr_and_Mrs_D
    Mr_and_Mrs_D about 5 years
    Better: file_path = os.path.join(script_dir, 'output03.txt')
  • Ângelo Polotto
    Ângelo Polotto about 5 years
    I tried on Windows OS that but I didn't have success.
  • Mr_and_Mrs_D
    Mr_and_Mrs_D about 5 years
    Interesting - can you print script_dir? Then turn it to absolute path as in script_dir = os.path.abspath(os.path.dirname(__file__))
  • Ângelo Polotto
    Ângelo Polotto about 5 years
    I will try that, if I succeed, I will change the answer.
  • lonstar
    lonstar almost 5 years
    Did not work on Windows. Path to file is correct but Python states "file not found" and shows the path with \\ separators.
  • Ronald
    Ronald about 4 years
    Backslashes are escape characters for several characters. If you happen to encounter \t like for example \top\directory, than '\t' is interpreted as a tab-character and your 'trick' fails. The best option is to use the raw string format r'C:\Users\chidu\Desktop\Skipper New\Special_Note.txt' which does not try to 'escape' characters.
  • pchtsp
    pchtsp over 3 years
    in Ubuntu and python3, I had to take the quotes from '__file__' so it became: fileDir = os.path.dirname(os.path.realpath(__file__))
  • Neuron
    Neuron over 2 years
    please use with data_folder.open() as f instead
  • Neuron
    Neuron over 2 years
    all upper case names should be reserved for constants
  • James Wong
    James Wong over 2 years
    In this case, wouldn't BASE_DIR be a constant? The parent folder of the script being run won't change during runtime.
  • FLAW
    FLAW over 2 years
    shouldn't you use os.path.join for 2091/data.txt ? woudn't it cause problems in window? \` & /`
  • Mauricio Gracia Gutierrez
    Mauricio Gracia Gutierrez over 2 years
    to avoid using / or \ you can os.path.join(path,'folderA','file.txt')