Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Relative paths break when executing Python script from Windows batch?

My Python script works perfectly if I execute it directly from the directory it's located in. However if I back out of that directory and try to execute it from somewhere else (without changing any code or file locations), all the relative paths break and I get a FileNotFoundError.

The script is located at ./scripts/bin/my_script.py. There is a directory called ./scripts/bin/data/. Like I said, it works absolutely perfectly as long as I execute it from the same directory... so I'm very confused.

Successful Execution (in ./scripts/bin/): python my_script.py

Failed Execution (in ./scripts/): Both python bin/my_script.py and python ./bin/my_script.py

Failure Message:

Traceback (most recent call last):
  File "./bin/my_script.py", line 87, in <module>
    run()
  File "./bin/my_script.py", line 61, in run
    load_data()
  File "C:\Users\XXXX\Desktop\scripts\bin\tables.py", line 12, in load_data
DATA = read_file("data/my_data.txt")
  File "C:\Users\XXXX\Desktop\scripts\bin\fileutil.py", line 5, in read_file
    with open(filename, "r") as file:
FileNotFoundError: [Errno 2] No such file or directory: 'data/my_data.txt'

Relevant Python Code:

def read_file(filename):
    with open(filename, "r") as file:
        lines = [line.strip() for line in file]
        return [line for line in lines if len(line) == 0 or line[0] != "#"]

def load_data():
    global DATA
    DATA = read_file("data/my_data.txt")
like image 969
asteri Avatar asked Feb 02 '26 08:02

asteri


2 Answers

Yes, that is logical. The files are relative to your working directory. You change that by running the script from a different directory. What you could do is take the directory of the script you are running at run time and build from that.

import os

def read_file(filename):
    #get the directory of the current running script. "__file__" is its full path
    path, fl = os.path.split(os.path.realpath(__file__))
    #use path to create the fully classified path to your data
    full_path = os.path.join(path, filename)
    with open(full_path, "r") as file:
       #etc
like image 162
RickyA Avatar answered Feb 04 '26 22:02

RickyA


Your resource files are relative to your script. This is OK, but you need to use

os.path.realpath(__file__)

or

os.path.dirname(sys.argv[0])

to obtain the directory where the script is located. Then use os.path.join() or other function to generate the paths to the resource files.

like image 44
Mario Rossi Avatar answered Feb 04 '26 23:02

Mario Rossi