10.1. File Path Relative

10.1.1. Rationale

  • Python works with both relative and absolute path

  • Path is relative to currently running script

  • Path separator \ (backslash) is used on Windows

  • Path separator / (slash) is used on *nix operating systems: Linux, macOS, BSD and other POSIX compliant OSes (excluding older versions of Windows)

  • In newer Windows versions both \ and / works the same

Relative paths works the same on Windows and *nix (Linux, macOS, BSD, etc.).

10.1.2. Current Directory

  • Path is relative to currently running script

  • . - Current directory

>>> FILE = 'myfile.txt'
>>> FILE = './myfile.txt'
>>> FILE = 'data/myfile.txt'
>>> FILE = './data/myfile.txt'

10.1.3. Upper Directory

  • Path is relative to currently running script

  • .. - Parent directory

>>> FILE = '../myfile.txt'
>>> FILE = '../data/myfile.txt'
>>> FILE = '../../myfile.txt'
>>> FILE = '../../data/myfile.txt'

10.1.4. Current Working Directory

  • Returns an absolute path to current working directory

>>> from pathlib import Path
>>>
>>>
>>> path = Path.cwd()
>>> print(path)  
/home/watney/

10.1.5. Good Practices

  • Never hardcode paths, use constant as a file name or file path

  • Convention (singular form): FILE, FILENAME, FILEPATH, PATH

  • Convention (plural form): FILES, FILENAMES, FILEPATHS, PATHS

  • Note, that PATH is usually used for other purposes (sys.path or os.getenv('PATH'))

>>> FILE = 'myfile.txt'
>>> FILES = [
...     'myfile.txt',
...     'myfile.csv',
... ]

10.1.6. Assignments

Code 10.1. Solution
"""
* Assignment: File Path Exception
* Required: yes
* Complexity: easy
* Lines of code: 6 lines
* Time: 3 min

English:
    1. Modify `result` function
    2. If `filename` exists, print 'Ok'
    3. If `filename` does not exist, print 'File not found'
    4. Run doctests - all must succeed

Polish:
    1. Zmodyfikuj funkcję `result`
    2. Jeżeli `filename` istnieje, wypisz 'Ok'
    3. Jeżeli `filename` nie istnieje, wypisz 'File not found'
    4. Uruchom doctesty - wszystkie muszą się powieść

Hints:
    * `try`
    * `except`
    * `else`
    * `open()`

Tests:
    >>> import sys; sys.tracebacklimit = 0
    >>> from inspect import isfunction

    >>> assert result is not Ellipsis, \
    'Assign result to variable: `result`'

    >>> assert isfunction(result), \
    'Variable `result` has invalid type, should be function'

    >>> result(__file__)
    Ok
    >>> result('_notexisting.txt')
    File not found
"""


def result(filename):
    ...


Code 10.2. Solution
"""
* Assignment: File Path Abspath
* Required: yes
* Complexity: easy
* Lines of code: 3 lines
* Time: 5 min

English:
    1. Define `path` with converted `filename` to absolute path
    2. To `result` assgin string:
        a. `file` if path is a file
        b. `directory` if path is a directory
        c. `missing` if path does not exist
    3. Run doctests - all must succeed

Polish:
    1. Zdefiniuj `path` z przekonwertowym `filename` do ścieżki bezwzględnej
    2. Do `result` przypisz ciąg znaków:
        a. `file` jeżeli ścieżka jest plikiem
        b. `directory` jeżeli ścieżka jest katalogiem
        c. `missing` jeżeli ścieżka nie istnieje
    3. Uruchom doctesty - wszystkie muszą się powieść

Hints:
    * `from pathlib import Path`
    * `Path.cwd()`
    * `Path()`
    * `Path.is_dir()`
    * `Path.is_file()`
    * `Path.exists()`

Tests:
    >>> import sys; sys.tracebacklimit = 0

    >>> assert isinstance(result, str), \
    'Result must be a str with: `file`, `directory` or `not exist`'

    >>> assert isinstance(abspath, Path), \
    'Use Path class from pathlib library to create a filepath'

    >>> current_directory = Path.cwd()
    >>> assert str(current_directory) in str(abspath), \
    'File Path must be absolute, check if you have current directory in path'

    >>> result
    'missing'
"""

from pathlib import Path


FILENAME = 'myfile.txt'

# Path: Absolute path to FILENAME
abspath = ...

# str: file, directory or missing
result = ...