wim
wim

Reputation: 363253

Prepend script's directory to a string

When writing throwaway scripts it's often needed to load a configuration file, image, or some such thing from the same directory as the script. Preferably this should continue to work correctly regardless of the directory the script is executed from, so we may not want to simply rely on the current working directory.

Something like this works fine if defined within the same file you're using it from:

from os.path import abspath, dirname, join

def prepend_script_directory(s):
    here = dirname(abspath(__file__))
    return join(here, s)

It's not desirable to copy-paste or rewrite this same function into every module, but there's a problem: if you move it into a separate library, and import as a function, __file__ is now referencing some other module and the results are incorrect.

We could perhaps use this instead, but it seems like the sys.argv may not be reliable either.

def prepend_script_directory(s):
    here = dirname(abspath(sys.argv[0]))
    return join(here, s)

How to write prepend_script_directory robustly and correctly?

Upvotes: 4

Views: 662

Answers (3)

ninjagecko
ninjagecko

Reputation: 91132

I would personally just os.chdir into the script's directory whenever I execute it. It is just:

import os
os.chdir(os.path.split(__file__)[0])

However if you did want to refactor this thing into a library, you are in essence wanting a function that is aware of its caller's state. You thus have to make it

prepend_script_directory(__file__, blah)

If you just wanted to write

prepend_script_directory(blah)

you'd have to do cpython-specific tricks with stack frames:

import inspect

def getCallerModule():
    # gets globals of module called from, and prints out __file__ global
    print(inspect.currentframe().f_back.f_globals['__file__'])

Upvotes: 3

SingleNegationElimination
SingleNegationElimination

Reputation: 156268

You want pkg_resources

import pkg_resources
foo_fname = pkg_resources.resource_filename(__name__, "foo.txt")

Upvotes: -1

msw
msw

Reputation: 43527

I think the reason it doesn't smell right is that $PYTHONPATH (or sys.path) is the proper general mechanism to use.

Upvotes: -1

Related Questions