[Tutor] inserting path to open a file from a variable

Felix Dietrich felix.dietrich at sperrhaken.name
Fri May 29 04:23:15 CEST 2015


richard kappler <richkappler at gmail.com> writes:

> If I run my script to open a file in Documents/MyScripts/fileMonitor which
> is where I'm doing my building and testing, with the variable rd1 (however
> created, my way and ConfigParser way both work) from within
> Documents/MyScripts/fileMonitor, the script fails with a
>
> Traceback (most recent call last):
>   File "21FileMonitor.py", line 28, in <module>
>     file = open(rd1, 'r')
> IOError: [Errno 2] No such file or directory:
> 'Documents/MyScripts/fileMonitor/log.txt'
>
> but if I run the exact same script from the Home directory, it works fine,
> does exactly what I expected it to do (ie. opens the files).
>
> I thought it might be because because I used Doc... instead of ~/Doc... for
> my path, but I got the same traceback.

"Documents/MyScripts/fileMonitor" is a relative path (does not start
with a '/'): it will be looked-up starting from the current working
directory.

Assuming the following directory tree:

    /
    └── home
        └── richard
            └── Documents
                └── MyScripts
                     └── fileMonitor
                          ├── fileMonitor.py
                          └── log.txt
        
and that you are inside the fileMonitor directory ('$' indicates
commands typed at a shell prompt):

    $ pwd
    /home/richard/Documents/MyScripts/fileMonitor

Now when you try to open a file with the path

    "Documents/MyScripts/fileMonitor/log.txt"

from within the fileMonitor directory you are trying to open a file at
(note that I use the '\' as line continuation marker)

    "/home/richard/Documents/MyScripts/fileMonitor/Documents/MyScripts/\
    cwd_example/log.txt"

To open "/home/richard/Documents/MyScripts/fileMonitor/log.txt" with the
current directory set to "/home/richard/Documents/MyScripts/fileMonitor"
you can refer to it as "log.txt" (also "../fileMonitor/log.txt" and all
sorts of less sensible addressing).

If your path on the other hand starts with a '/' it is an absolute path
starting with the directory tree root: the path
"/home/richard/Documents/MyScripts/cwd_example/log.txt" will always
refer to "/home/richard/Documents/MyScripts/cwd_example/log.txt" no
matter the current working directory.


Another example:

    /
    └── home
        └── felix
            └── Documents
                └── MyScripts
                    └── cwd_example
                        └── cwd

Here is the content of cwd:

    #!/usr/bin/python
    import os
    print(os.getcwd())

Make it executable:

    $ pwd
    /home/felix/Documents/MyScripts/cwd_example/
    $ chmod +x cwd

Note that it is not unusual for a script to drop its file extension when
it is made executable; the language used to implement is not important
anymore and the executable becomes not distinguishable by extension from
other executables whether written in an interpreted language or binary.

The shebang ("#!") line acts as magic to identify the interpreter to
use.

Some examples:

    $ pwd
    /home/felix/Documents/MyScripts
    $ cwd_example/cwd
    /home/felix/Documents/MyScripts     
    $ /home/felix/Documents/MyScripts/cwd_example/cwd
    /home/felix/Documents/MyScripts     

    $ pwd
    /home/felix/Documents/MyScripts/cwd_example/log-dir
    $ ../cwd # .. = parent directory
    /home/felix/Documents/MyScripts/cwd_example/log-dir     
    $ /home/felix/Documents/MyScripts/cwd_example/cwd
    /home/felix/Documents/MyScripts/cwd_example/log-dir     

    $ pwd
    /home/felix/Documents/MyScripts/cwd_example/
    $ ./cwd # . = current directory
    /home/felix/Documents/MyScripts/cwd_example/     
    $ /home/felix/Documents/MyScripts/cwd_example/cwd
    /home/felix/Documents/MyScripts/cwd_example/

Again the absolute path works independently of the current working
directory.  ".." refers to the previous directory; "." to the current
one.  And the working directory is not related to the directory the
executable resides in – though they might happen to be the same.

The following only works when either '.' or
"/home/felix/Documents/MyScripts/cwd_example/" are part of the PATH
environment variable:

    $ pwd
    /home/felix/Documents/MyScripts/cwd_example/
    $ cwd

Regarding the '~': I do not think that (most?) python functions
automatically expand the tilde to the user's directory; instead look at
/os.path.expanduser/:

    >>> os.path.expanduser("~/Documents")
    '/home/felix/Documents'

Have a look at the modules /os/ and /os.path/ (also /pathlib/ for >=3.4)
functions /os.chdir/, /os.getcwd/, /os.expanduser/ specifically.

/sys.path/ is also related to the current working directory and relative
paths and it will come in handy when you import your own modules not
residing in any of the default directories while running the script with
a different working directory than its location.

--
Felix Dietrich


More information about the Tutor mailing list