2

I'm writing a Python library which which you can load an object from a file and do something with it. For convenience, I'd like to make it so that people can provide three kinds of paths:

  1. A path starting with a "/", which will be interpreted as an absolute path

  2. A path starting with a "~/", which will be interpreted as relative to the user's home directory (for which I plan to use os.path.expanduser)

  3. A path starting with neither, which would be interpreted as relative to the directory of the top-level script that is importing my library.

My question is: what is the best way of approaching the third case? The two ways I have come across on Stack Overflow are both kind of klugey:

1)

import __main__
if hasattr(__main__, "__file__"):
    script_dir = os.path.dirname(os.path.abspath(__main__.__file__))
import inspect
frame_info = inspect.stack()[-1]
mod = inspect.getmodule(frame_info[0])
script_dir = os.path.dirname(mod.__file__)

Obviously both of these will fail in the case that we're running from an interactive terminal or something, and in that case I would want to fall back to just treating it as an absolute path.

Anyway, I get the sense that using inspect like this in a library is frowned upon, but the other way seems klugey as well. Is there a better way to do this that I'm unaware of?

MarcTheSpark
  • 473
  • 5
  • 14
  • 1
    You haven't mentioned the `working directory`, are you aware of that? An unprefixed path is common practice to be relative to the current working directory. You should also take a look at the built-in `pathlib` package before you create your package – Mandera Nov 02 '20 at 21:54
  • Does this answer your question? [How to get filename of the \_\_main\_\_ module in Python?](https://stackoverflow.com/questions/606561/how-to-get-filename-of-the-main-module-in-python) – mkrieger1 Nov 02 '20 at 21:55
  • Sounds like there isn't actually a problem with the first approach other than you finding it "klugey", is there? – mkrieger1 Nov 02 '20 at 21:57
  • @mkrieger1 I guess the klugeyness was a tip off that I was doing something a bit funny, since it's something for which I would expect a simple answer. In this case, I was looking for `getcdw`, even though it's slightly different. – MarcTheSpark Nov 03 '20 at 11:37

1 Answers1

2

Use the built-in package pathlib's getcwd method. It defaults to the root folder of the top package.

Will not work if you change the working directory. Although, an unprefixed path is common practice to be relative to the working directory.

import pathlib
print(pathlib.Path.cwd())

>>> A:\Programming\Python\generalfile
Mandera
  • 2,647
  • 3
  • 21
  • 26
  • 1
    Thank you for this -- I believe the `working directory` is exactly what I was looking for. Of course, if you run a script from a different directory, then that is different from the directory of the script, but I think in that case maybe you still want the working directory, if that's the convention for unprefixed paths. Quick question: is there a difference between pathlib.Path.cwd() and os.getcwd()? Why use one over the other? – MarcTheSpark Nov 03 '20 at 05:53
  • [`pathlib` actually uses `os.getcwd()`.](https://github.com/python/cpython/blob/9568622c9983b682b2a2a7bacfd3c341028ea099/Lib/pathlib.py#L1125) I prefer using **pathlib** as having that extra layer of a built-in package designed specifically for filesystem paths seems more stable to me – Mandera Nov 03 '20 at 07:48