views:

49

answers:

2

I would like to see what is best way to determine current script directory in python?

I discovered that two to the many ways of calling python code, it is hard to find a good solution.

Here are some problems:

  • __file__ is not defined if the script is executed with exec, execfile
  • __module__ is defined only in modules

Use cases:

  • ./myfile.py
  • python myfile.py
  • ./somedir/myfile.py
  • python somedir/myfile.py
  • exec('myfile.py') (from another script, that can be located in another directory and that can have another current directory.

I know that there is no perfect solution, because in some cases but I'm looking for the best approach that solved most of the cases.

The most used approach is os.path.dirname(os.path.abspath(__file__)) but this is really doesn't work if you execute the script from another one with exec().

A: 

Would

import os
cwd = os.getcwd()

do what you want? I'm not sure what exactly you mean by the "current script directory". What would the expected output be for the use cases you gave?

Will McCutchen
It wouldn't help. I believe @bogdan is looking for the directory for the script that is at the top of the call stack. i.e. in all his/her cases, it should print the directory where 'myfile.py' sits. Yet your method would only print the directory of the file that calls `exec('myfile.py')`, same as `__file__` and `sys.argv[0]`.
Zhang18
Yeah, that makes sense. I just wanted to make sure @bogdan wasn't overlooking something simple, and I couldn't tell exactly what they wanted.
Will McCutchen
+3  A: 
os.path.dirname(os.path.abspath(__file__))

is indeed the best you're going to get.

It's unusual to be executing a script with exec/execfile; normally you should be using the module infrastructure to load scripts. If you must use these methods, I suggest setting __file__ in the globals you pass to the script so it can read that filename.

There's no other way to get the filename in execed code: as you note, the CWD may be in a completely different place.

bobince