How to normalize a relative path using pathlib

Question:

I’m trying to use relative paths in Python, and I want to put my csv files in a separate folder from my python code.

My python program is in the following folder:

G:projectscode

I want to read this file which is one level up:

G:projectsdatasales.csv

How do I specify a path using pathlib that is one level up from my current working folder? I don’t want to change the current working folder.

I tried this:

from pathlib import Path
file = Path.cwd() /'..'/'data'/'sales.csv'

But now the ‘file’ variable equals this:

'G:/projects/code/../data/sales.csv'

I read through the docs and either it isn’t explained there or I’m just missing it.

Asked By: Dread

||

Answers:

Do you mean “read my csv files”?

The import keyword has a different meaning in Python (you import only other Python modules).

In any case, in order to read a file located one folder above your Python file, you can use this:

import os
filePath = os.path.dirname(__file__)+'/../'+fileName
fileDesc = open(filePath)
fileData = fileDesc.read()
fileDesc.close()
...
Answered By: goodvibration
print(
    Path(__file__).parent,  # the folder
    Path(__file__).parent.parent,  # the folder's parent
    sep='n'
)

print(
    Path(
        Path(__file__).parent.parent, 'hello.py'
    )
)

results in

C:UsersisikDesktopPythonMessAroundprojectmodule
C:UsersisikDesktopPythonMessAroundproject
C:UsersisikDesktopPythonMessAroundprojecthello.py

with this file structure

-project
    -module
        -__init__.py
    -hello.py
    -__init__.py

while the code is located inside project.module.__init__.py

Answered By: Işık Kaplan

Although it’s not a problem that your path includes ‘..’ (you can still use this path to open files, etc. in Python), you can normalize the path using resolve():

from pathlib import Path
path = Path.cwd() / '..' / 'data' / 'sales.csv'
print(path)  # WindowsPath('G:/projects/code/../data/sales.csv')
print(path.resolve())  # WindowsPath('G:/projects/data/sales.csv')

NB: I personally would name a variable that contains a path path, not file. So you could later on do file = open(path).

Answered By: wovano

here is an example I used:

import json
from pathlib import Path

def read_files(folder_name, file_name):
    base_path = Path.cwd().joinpath('configs','resources')
    path = base_path.joinpath(folder_name,file_name)
    open_file = open(path,'r')
    return json.load(open_file.read())
Answered By: shani

This is pretty old, but I happened on it looking for something else.

Oddly you never got a direct, obvious, answer — you want the parent property:

from pathlib import Path
file = Path.cwd().parent / 'data' / 'sales.csv'

Note that some of the answers that say you want __file__ rather than the current working directory may be correct (depending on your use case), in which case it’s:

from pathlib import Path
file = Path(__file__).parent.parent / 'data' / 'sales.csv'

(parent of the python file is the code dir, parent of that is the projects dir.

However, It’s not great practice to refer to your data by its relative path to your code — I think using the cwd is a better option — though what you should do is pass the path to the data in to the script via sys.argv.

Answered By: Christopher Barker
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.