1

[My original post, unforgivably, left out the word "not" (now emphasized below) from the second paragraph.]

Does Python offer a stable way to access the initial working directory of the current process?

(Note that the solution may NOT assume anything about when it is executed relative to the program's start-up.)

The only way to do this that I can think of is something like:

import os
def getiwd():
    return os.environ['PWD']

...which is rather lame, even if one puts aside the question of its viability under Windows, since any other part of the code (e.g. the client code, or other modules loaded by it) is free to modify os.environ['PWD']. IOW, it is "unstable".

kjo
  • 33,683
  • 52
  • 148
  • 265
  • 1
    Doesn't `os.getcwd()` work for you? – João Silva Aug 18 '12 at 22:45
  • 1
    I think you have to save it yourself if you change directories after startup. – jterrace Aug 18 '12 at 22:45
  • @kjo: Was that supposed to be "may *not* assume"? – Mechanical snail Aug 18 '12 at 22:48
  • @João It does not work if any code anywhere changes the working directory before you call that. –  Aug 18 '12 at 23:49
  • 1
    @Mechanicalsnail: Right you are! Of all the idiotic typos I could have made, I managed to make probably the absolute worst one... I wish I could cancel the post and start over... Too late now. My apologies to those who replied in vain. – kjo Aug 19 '12 at 18:11

2 Answers2

1

The way you should get the "initial" working directory is to get it initially and save it somewhere else. For this purpose nothing is needed beyond the os.getcwd() that you're probably aware of.

There is no reason for a language to provide it any other way - the current working directory is supposed to be something that can change.

Amber
  • 507,862
  • 82
  • 626
  • 550
  • I apologize for the typo in the original post, since it negated my intent to specifically rule out solutions like the one you gave. (See also my comments to carrot-top and to Mechanical Snail.) That said, I *did* specify quite clearly that I want *the working directory at start-up*. I ***do not want*** the current working directory. – kjo Aug 19 '12 at 18:22
  • @kjo I'm aware of what you were asking for. My point is that there is no other way to get the "working directory at start-up" aside from "getting the current working directory at start-up and saving it somewhere else". Python does not preserve data about the start-up working directory for you. – Amber Aug 19 '12 at 19:35
-1

For your startup working directory (as one of the first lines of your script) :

ini_path = os.getcwd()   

For the path to your script, use sys.path[0].

Test code (DO try this at home):

import sys, os, inspect
ini_path = os.getcwd()

def ppaths(d=''):
    print('sys.path[0]:     {}'.format(sys.path[0]))
    print('ini_path:        {}'.format(ini_path))
    print('os.getcwd:       {}'.format(os.getcwd())) 
    print('inspect.getfile: {}'.format(inspect.getfile(inspect.currentframe())))
    print('os.dirfile:      {}'.format(
               os.path.dirname(inspect.getfile(inspect.currentframe()))))
    if d:
        print('==== Changing to "{}" '.format(d))
        os.chdir(d)


print()
ppaths('/')
ppaths('Users')
ppaths()

On my system (running from inside an editor), prints:

sys.path[0]:     /private/var/folders/00/kbqj5nt54m99z5gyffy8fksm0000gp/T/Cleanup At Startup
ini_path:        /Users/andrew
os.getcwd:       /Users/andrew
inspect.getfile: /private/var/folders/00/kbqj5nt54m99z5gyffy8fksm0000gp/T/Cleanup At Startup/untitled text 3-367027656.416
os.dirfile:      /private/var/folders/00/kbqj5nt54m99z5gyffy8fksm0000gp/T/Cleanup At Startup
==== Changing to "/" 
sys.path[0]:     /private/var/folders/00/kbqj5nt54m99z5gyffy8fksm0000gp/T/Cleanup At Startup
ini_path:        /Users/andrew
os.getcwd:       /
inspect.getfile: /private/var/folders/00/kbqj5nt54m99z5gyffy8fksm0000gp/T/Cleanup At Startup/untitled text 3-367027656.416
os.dirfile:      /private/var/folders/00/kbqj5nt54m99z5gyffy8fksm0000gp/T/Cleanup At Startup
==== Changing to "Users" 
sys.path[0]:     /private/var/folders/00/kbqj5nt54m99z5gyffy8fksm0000gp/T/Cleanup At Startup
ini_path:        /Users/andrew
os.getcwd:       /Users
inspect.getfile: /private/var/folders/00/kbqj5nt54m99z5gyffy8fksm0000gp/T/Cleanup At Startup/untitled text 3-367027656.416
os.dirfile:      /private/var/folders/00/kbqj5nt54m99z5gyffy8fksm0000gp/T/Cleanup At Startup

Now, run it from Bash:

kitchen:SO andrew$ pwd
/Users/andrew/bin/SO
kitchen:SO andrew$ ls ins.py
ins.py
kitchen:SO andrew$ ./ins.py

sys.path[0]:     /Users/andrew/bin/SO
ini_path:        /Users/andrew/bin/SO
os.getcwd:       /Users/andrew/bin/SO
inspect.getfile: ./ins.py
os.dirfile:      .
==== Changing to "/" 
sys.path[0]:     /Users/andrew/bin/SO
ini_path:        /Users/andrew/bin/SO
os.getcwd:       /
inspect.getfile: ./ins.py
os.dirfile:      .
==== Changing to "Users" 
sys.path[0]:     /Users/andrew/bin/SO
ini_path:        /Users/andrew/bin/SO
os.getcwd:       /Users
inspect.getfile: ./ins.py
os.dirfile:      .
kitchen:SO andrew$ 

Run from a different directory in Bash:

kitchen:SO andrew$ cd ..
kitchen:bin andrew$ ./SO/ins.py

sys.path[0]:     /Users/andrew/bin/SO
ini_path:        /Users/andrew/bin
os.getcwd:       /Users/andrew/bin
inspect.getfile: ./SO/ins.py
os.dirfile:      ./SO
==== Changing to "/" 
sys.path[0]:     /Users/andrew/bin/SO
ini_path:        /Users/andrew/bin
os.getcwd:       /
inspect.getfile: ./SO/ins.py
os.dirfile:      ./SO
==== Changing to "Users" 
sys.path[0]:     /Users/andrew/bin/SO
ini_path:        /Users/andrew/bin
os.getcwd:       /Users
inspect.getfile: ./SO/ins.py
os.dirfile:      ./SO

In ALL cases, sys.path[0] points to the absolute path of the start-up script.

In order to get os.getcwd() on start-up to work, you can see that you will also have to parse the leading path to the name of the script -- more work....

More in this SO post.

Community
  • 1
  • 1
the wolf
  • 34,510
  • 13
  • 53
  • 71
  • @Amber: Respectfully, that is incorrect. `sys.path[0]` refers to the start-up directory of the script unless changed by the script itself. See example code... – the wolf Aug 19 '12 at 00:03
  • It's possible for `sys.path[0]` to be the empty string -- such as in the Python shell -- so to handle that you'd probably want `os.path.abspath(sys.path[0])`. Also `inspect.getfile((inspect.currentframe()))` returns `''` there. – martineau Aug 19 '12 at 01:13
  • @carrot-top Except the OP isn't asking for the absolute path to the script, but rather, to the initial value of the working directory (which ISN'T always the script location). Also, `sys.path` is also not immune to being changed (any more than the current working directory is). – Amber Aug 19 '12 at 02:22
  • (Notice that even before you `os.chdir()`, the values of `os.getcwd()` and `sys.path[0]` are different.) – Amber Aug 19 '12 at 02:25
  • @martineau: You are correct (as usual) but an easy fix: `import __main__ as main; print hasattr(main, '__file__')` will tell if you are in the shell or not. – the wolf Aug 19 '12 at 03:18
  • @Amber: `(Notice that even before you os.chdir(), the values of os.getcwd() and sys.path[0] are different.)` That was exactly what I was trying to demonstrate. – the wolf Aug 19 '12 at 03:20
  • @carrot-top Yes, but the point is that `sys.path[0]` is the wrong one of those two values. The OP wants the `getcwd()` from the start of the program, even if it has later been `chdir()`'d. – Amber Aug 19 '12 at 03:24
  • @carrot-top: I apologize for the typo in my original post, since it basically negated the clarification I had included precisely to rule out solutions like the one you proposed. (See also my comment to Mechanical Snail above.) – kjo Aug 19 '12 at 18:18
  • @kjo: I am unaware of a method to get the startup working directory without saving it first. Why are you adverse to saving it at start-up? – the wolf Aug 19 '12 at 21:16
  • @carrot-top: "> Why are you adverse to saving it at start-up?" Because I am writing "library code", which does not have the luxury to execute at start-up (the earliest it can execute anything is when it is first imported, and that can happen arbitrarily late after start-up). – kjo Aug 20 '12 at 01:16
  • @kjo: That makes sense. Difficult problem. So you are looking for the start-up working directory of the parent (or grandparent, etc) script at the moment the parent (or grandparent) started even if that was some time before your module is imported in a portable way. I am not optimistic.... Best! – the wolf Aug 20 '12 at 01:26