5

I'm looking for a replacement of

import os
package_dir = os.path.dirname(os.path.abspath(__file__))
file_path = os.path.join(package_dir,'foo.csv')

My working path isn’t the path of the file. So when I want to load a file, I need a way to generate the relative path compared to my working directory.

I want to update to pathlib (or whatever else is out there). But what is the nicest way to do the same?

I found https://stackoverflow.com/a/44188489, but I don't think this solution looks better than my current way.

Remark:

It's not a duplicate of How to properly determine current script directory?, since I explicitly asked about the nicest way. Most of the solutions in the other post don't look nice, or are already mentioned in the my question. The solution

Path(__file__).with_name("foo.csv")

given here is much better than the solutions given in the other question, since it's easy to understand, and a really pythonic way to solve it. If this question was a dublicate, on the other post an equally good answer would exist.

subjord
  • 109
  • 1
  • 10
  • your first line looks perfectly fine to me. i *think* you don't need the os.path.abspath portion of it. As for pathlib, it comes into play once you have a path. its just a smarter way to deal with file paths. so it makes the 2nd line easier to write, but doesnt really do much for the first. – Paritosh Singh Jan 20 '19 at 18:05
  • Why do you want to change? What does your current solution do poorly? – John Gordon Jan 20 '19 at 18:05
  • 1
    The current version with os. is relative old. Pathlib was invented to replace most of the os. functionality. That's why I'm looking for a new way to do the same with Pathlib. Maybe there is even a solution that is more comfortable, than the current solution. – subjord Jan 20 '19 at 18:13

1 Answers1

8

If you're looking to do the same with pathlib, it could look like this:

from pathlib import Path

package_dir = Path(__file__).parent.absolute()
file_path = package_dir.joinpath("foo.csv")

Unless you're changing current working directory, you may not really need/want to use .absolute().

If you actually do not need to know what package_dir would be, you can also just get the file_path directly:

file_path = Path(__file__).with_name("foo.csv").absolute()

Which gives you new Path replacing the file name.

Ondrej K.
  • 8,841
  • 11
  • 24
  • 39
  • awesome :) This solution looks really clean and easy to understand. – subjord Jan 20 '19 at 18:28
  • I gotta admit, I really do like `pathlib` and I think it does allow for the whole files handling to be significantly cleaned up. – Ondrej K. Jan 20 '19 at 18:29
  • I had a problem with your one line solution and subfolders. I used this instead: ``Path(__file__).parent.joinpath("output/foo.csv")`` – subjord Jan 20 '19 at 19:54
  • @subjord Could you perhaps be a little more specific about nature of the problem? We could try to find a solution and/or improve the answer accordingly. – Ondrej K. Jan 20 '19 at 20:09
  • I tried to use Path(__file__).with_name("../folder/foo.csv") which leads to an error message. – subjord Jan 22 '19 at 12:05
  • Error message being? `.with_name()` does not seem to be anything that appeared later in the game. `__file__` would not work in an interactive python session as it's not defined. Hence my curiosity if there some other pitfall missed that should have been mentioned / documented. – Ondrej K. Jan 22 '19 at 12:10
  • If in the string in the brackets of `.with_name("")` contains a backslash, I get the following error message: ``raise ValueError("Invalid name %r" % (name))`` – subjord Jan 23 '19 at 14:31
  • I'm referring to the handy one line solution `file_path = Path(__file__).with_name("foo.csv")` – subjord Jan 23 '19 at 14:33
  • I see. Yes, `with_name()` replaces the name portion, i.e. same path with a different filename. So, this method cannot be used if `name` passed is actually not just a pathname, but a (relative) path with directory bit in it. I.e. with `\ ` for `WindowPath` or `/` for `PosixPath`. – Ondrej K. Jan 23 '19 at 17:36