Select to view content in your preferred language

Finding Python script home folder

8392
8
11-06-2016 10:47 PM
curtvprice
MVP Alum
0 8 8,392

Often we have scripts that require a home folder location for the script to locate related files -- for example, layer files, data distributed with the tool that it uses, etc.  Here are some methods to find that location.

os.path.dirname(sys.argv[0]) or os.path.dirname(__file__)

Both these locations find the path of the currently running Python script file.

Usually, __file__ is the best choice.
See: Difference between __file__ and sys.argv[0] (StackOverflow)

Toolbox (.tbx) validation code

In .tbx script tool validation code, sys.argv[0] returns an empty string, but  __file__ will be the path to the function packed in a string like this: u'C:\\test\\Toolbox.tbx#Script_z.InitializeParameters.py'

In this case, the location of the tbx would be: os.path.dirname(__file__)

ModelBuilder tbx location

The ModelBuilder tbx location can be found using os.path.realpath and the Calculate Value tool with this code block:

# Call with expression: home()
import os
def home():
  return os.path.realpath(".")‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Map document location ("Home folder" in ArcMap or Pro)

Some script tools (always run from ArcMap or Pro) may need to locate data relative to the .mxd or .aprx location:

# ArcMap
here = os.path.dirname(arcpy.mapping.MapDocument("CURRENT").filePath‍)‍‍‍‍‍
# ArcGIS Pro
here = arcpy.mp.ArcGISProject("CURRENT").filePath‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
8 Comments
DanPatterson_Retired
MVP Emeritus

I would caution against just relying on just...  __file__ ... it won't exist if you are just running a script.

__file__ can be exploited if you have imported a module however, so always check using dir() to confirm the existence of a __file__ property first.

For example

>>> import os
>>> import sys

>>> dir()
['__all__', '__builtins__', '__cached__', '__doc__', '__loader__', '__name__', 
'__package__', '__spec__', '_data', ...snip..., 'art', ... snip ..., 'os',
 ... snip ..., 'sys']

>>> # ... now 'art' is an imported module

>>> dir(art)
['__all__', '__builtins__', '__cached__', '__doc__', '__file__',... snip ...]

>>> # ... it has a __file__ property which

>>> f = os.path.dirname(art.__file__)
>>> f
'/private/var/mobile/Containers/Shared/AppGroup/...some weird location thing .../Pythonista3/Documents/site-packages-3'
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
Things can c

hange with the operating system and the version of python you are using. Fortunately ArcMap and Pro have a restricted number of options.... python runs on anything

curtvprice
MVP Alum
__file__ ... it won't exist if you are just running a script.

I do not understand, sir.

DanPatterson_Retired
MVP Emeritus

Curtis ...__file__ doesn't exist as a property for the script... it does for imported modules.

try it python in windows and OSwhater machines, they behave differently.  sys.argv[0] gives you the running script from which you can parse the path. If you import a toolbox or a python module (aka another script), it will have a __file__ property... just not the script that you are running... try it on different operating systems, and my comments were directed to python not arcmap explicitly

curtvprice
MVP Alum

__file__ ... it won't exist if you are just running a script...

__file__ doesn't exist as a property for the script... it does for imported modules.

??? I must be very dense. Please enlighten me.

In ArcGIS (or anywhere else) the main startup script (.py, .pyt, tbx[validation code]) would be the context you would normally need the pathname to find the tool's associated files, and I seem to be able to use __file__ there just fine. The dialog below is OSX.

Marcie:~ curtis$ cat x.py
print(__file__)
Marcie:~ curtis$ python x.py
x.py
Marcie:~ curtis$ python `pwd`/x.py
/Users/curtis/x.py‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
DanPatterson_Retired
MVP Emeritus

start python on your system... do absolutely nothing... do a 'dir'  do a locals().keys(), run a script with

import sys

script = sys.argv[0]

what is script? Does __file__ exist in dir or locals.keys?  On my operating system(s), it doesn't unless I import a module (as in my example), then __file__ exists and it refers to the module, not the script

curtvprice
MVP Alum

Dan, I am still dense here. There is no script file (ie module) here in this dialog below except the current process. Why would one expect __file__ or sys.argv[0] to be defined in this context at all?

python
>>> import sys
>>> sys.argv[0]
''
>>> __file__
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
NameError: name '__file__' is not defined
>>>‍‍‍‍‍‍‍‍‍
DanPatterson_Retired
MVP Emeritus

To quote you...

os.path.dirname(sys.argv[0]) or os.path.dirname(__file__).
Both these locations find the path of the currently running Python script file.
Usually, __file__ is the best choice.

__file__ doesn't exist  for a currently running script unless it is imported..., was my point... see below

>>> sys.argv[0]
'/private/var/mobile/Containers/Shared/AppGroup/A9DDA80F-9432-45DA-B931-2E9386579AE6/Pythonista3/Documents/Python_3_scripts/np/ein_geom.py'

>>> dir(ein_geom)
Traceback (most recent call last):
  File "<string>", line 1, in <module>
NameError: name 'ein_geom' is not defined

>>> import ein_geom

>>> dir(ein_geom)

['__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_data', 'area_demo', 'art', 'e_area', 'e_leng', 'ft', 'inspect', 'leng_demo', 'main', 'np', 'poly2pnts', 'script', 'sys']

>>> ein_geom.__file__
'/private/var/mobile/Containers/Shared/AppGroup/A9DDA80F-9432-45DA-B931-2E9386579AE6/Pythonista3/Documents/Python_3_scripts/np/ein_geom.py'

>>> # even thought the script was run, __file__ doesn't exist, until it is imported.
>>> making sys.argv[0] the only sure way to know what script is being run
curtvprice
MVP Alum

I guess as far as I know I've never run a script in this way, which I still don't follow. Maybe because have only used windows and unix??

About the Author
PhD candidate (Geology), South Dakota Mines; Hydrologist, U.S. Geological Survey.
Labels