Python - File Path not found if script run from another directory

Viewed 27

I'm trying to run a script that works without issue when I run using in console, but causes issue if I try to run it from another directory (via IPython %run <script.py>)

The issue comes from this line, where it references a folder called "Pickles".

 with open('Pickles/'+name+'_'+date.strftime('%y-%b-%d'),'rb') as f:
            obj = pickle.load(f)

In Console:

python script.py <---works!

In running IPython (Jupyter) in another folder, it causes a FileNotFound exception.

How can I make any path references within my scripts more robust, without putting the whole extended path?

Thanks in advance!

2 Answers

Since running in the console the way you show works, the Pickles directory must be in the same directory as the script. You can make use of this fact so that you don't have to hard code the location of the Pickles directory, but also don't have to worry about setting the "current working directory" to be the directory containing Pickles, which is what your current code requires you to do.

Here's how to make your code work no matter where you run it from:

with open(os.path.join(os.path.dirname(__file__), 'Pickles', name + '_' + date.strftime('%y-%b-%d')), 'rb') as f:
    obj = pickle.load(f)

os.path.dirname(__file__) provides the path to the directory containing the script that is currently running.

Generally speaking, it's a good practice to always fully specify the locations of things you interact with in the filesystem. A common way to do this as shown here.

UPDATE: I updated my answer to be more correct by not assuming a specific path separator character. I had chosen to use '/' only because the original code in the question already did this. It is also the case that the code given in the original question, and the code I gave originally, will work fine on Windows. The open() function will accept either type of path separator and will do the right thing on Windows.

You have to use absolute paths. Also to be cross platform use join:

  • First get the path of your script using the variable __file__
  • Get the directory of this file with os.path.dirname(__file__)
  • Get your relative path with os.path.join(os.path.dirname(__file__), "Pickles", f"{name}_{date.strftime('%y-%b-%d')}")

it gives you:

with open(os.path.join(os.path.dirname(__file__), "Pickles", f"{name}_{date.strftime('%y-%b-%d')}"), 'rb') as f:
    obj = pickle.load(f)
Related