Hello python devs. One thing which appears to be pretty common in many scripts is figuring out module's parent directory path. I often find myself writing: HERE = os.path.abspath(os.path.dirname(__file__)) ...at the top of a module. Also, it is not rare to do further concatenations in order to declare where static files are located: CONF_FILE = os.path.abspath(os.path.join(HERE, 'app.conf')) CERT_FILE = os.path.abspath(os.path.join(HERE, 'cert.pem')) THIS_FILE = os.path.abspath(os.path.join(HERE, __file__)) A quick search within Python source code shows this is indeed a very common pattern: $ find . -name \*.py | xargs grep "os\.path" | grep __file__ Just some examples (there are *many*): http://hg.python.org/cpython/file/186f6f56f4bc/Lib/distutils/tests/__init__.... http://hg.python.org/cpython/file/186f6f56f4bc/PCbuild/build_tkinter.py#l11 http://hg.python.org/cpython/file/186f6f56f4bc/PCbuild/build_ssl.py#l68 http://hg.python.org/cpython/file/186f6f56f4bc/Tools/msi/uisample.py#l2 http://hg.python.org/cpython/file/186f6f56f4bc/Lib/distutils/tests/test_conf... http://hg.python.org/cpython/file/186f6f56f4bc/Lib/unittest/test/testmock/__... http://hg.python.org/cpython/file/186f6f56f4bc/Lib/pydoc.py#l2463 I think there's space for improvements here so my proposal is to add a simple os.path.here() function working like this:
# assuming /home/giampaolo/app/run.py is the current module: os.path.here() /home/giampaolo/app/ os.path.here(__file__) /home/giampaolo/app/run.py os.path.here('..') /home/giampaolo/
The implementation is pretty straightforward: def here(concat=None): """Return the absolute path of the parent directory where the script is defined. """ here = os.path.abspath(os.path.dirname(__file__)) if concat is not None: here = os.path.abspath(os.path.join(here, concat)) return here Thoughts? -- Giampaolo - http://grodola.blogspot.com
On 19 February 2014 16:52, Giampaolo Rodola' <g.rodola@gmail.com> wrote:
The implementation is pretty straightforward:
def here(concat=None): """Return the absolute path of the parent directory where the script is defined. """ here = os.path.abspath(os.path.dirname(__file__)) if concat is not None: here = os.path.abspath(os.path.join(here, concat)) return here
So if I do from os.path import here and get the above function what happens when I call it in another module?
Thoughts?
This encourages writing code that makes assumptions that break when run from a zip file. I think that encouraging pkgutil.get_data() for loading resources that are stored adjacent to a module is better. Oscar
On Wed, Feb 19, 2014 at 6:04 PM, Oscar Benjamin <oscar.j.benjamin@gmail.com>wrote:
On 19 February 2014 16:52, Giampaolo Rodola' <g.rodola@gmail.com> wrote:
The implementation is pretty straightforward:
def here(concat=None): """Return the absolute path of the parent directory where the script is defined. """ here = os.path.abspath(os.path.dirname(__file__)) if concat is not None: here = os.path.abspath(os.path.join(here, concat)) return here
So if I do from os.path import here and get the above function what happens when I call it in another module?
Ouch! You're right, I naively didn't take that into account. =) I guess there are ways to inspect the caller's module name but I'm not gonna push for that. Sorry for the noise.
That IS an option... ```python import inspect ... module_path = inspect.stack()[1][0].f_globals['__file__'] ``` On Wed, Feb 19, 2014 at 11:18 AM, Giampaolo Rodola' <g.rodola@gmail.com>wrote:
On Wed, Feb 19, 2014 at 6:04 PM, Oscar Benjamin < oscar.j.benjamin@gmail.com> wrote:
On 19 February 2014 16:52, Giampaolo Rodola' <g.rodola@gmail.com> wrote:
The implementation is pretty straightforward:
def here(concat=None): """Return the absolute path of the parent directory where the script is defined. """ here = os.path.abspath(os.path.dirname(__file__)) if concat is not None: here = os.path.abspath(os.path.join(here, concat)) return here
So if I do from os.path import here and get the above function what happens when I call it in another module?
Ouch! You're right, I naively didn't take that into account. =) I guess there are ways to inspect the caller's module name but I'm not gonna push for that. Sorry for the noise.
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
-- Ryan If anybody ever asks me why I prefer C++ to C, my answer will be simple: "It's becauseslejfp23(@#Q*(E*EIdc-SEGFAULT. Wait, I don't think that was nul-terminated."
On 19 February 2014 17:18, Giampaolo Rodola' <g.rodola@gmail.com> wrote:
On Wed, Feb 19, 2014 at 6:04 PM, Oscar Benjamin <oscar.j.benjamin@gmail.com> wrote:
On 19 February 2014 16:52, Giampaolo Rodola' <g.rodola@gmail.com> wrote:
The implementation is pretty straightforward:
def here(concat=None): """Return the absolute path of the parent directory where the script is defined. """ here = os.path.abspath(os.path.dirname(__file__)) if concat is not None: here = os.path.abspath(os.path.join(here, concat)) return here
So if I do from os.path import here and get the above function what happens when I call it in another module?
Ouch! You're right, I naively didn't take that into account. =) I guess there are ways to inspect the caller's module name but I'm not gonna push for that. Sorry for the noise.
There are ways to do it. namedtuple does it here: http://hg.python.org/cpython/file/e6016fffc894/Lib/collections/__init__.py#l... But I think that's considered to be an unfortunate mistake by some. Oscar
participants (3)
-
Giampaolo Rodola' -
Oscar Benjamin -
Ryan Gonzalez