7.1. File Path¶
7.1.1. Rationale¶
Python works with both relative and absolute path
Path separator
\
(backslash) is used on WindowsPath separator
/
(slash) is used on*nix
operating systems: Linux, macOS, BSD and other POSIX compliant OSes (excluding Windows)In newer Windows versions both
\
and/
works the same
Absolute path on Windows:
>>> FILE = r'C:\Users\Watney\myfile.txt'
Absolute path on *nix
(Linux, macOS, BSD, etc.):
>>> FILE = '/tmp/myfile.txt'
Relative paths works the same on Windows and *nix
(Linux, macOS, BSD, etc.):
>>> FILE = 'myfile.txt'
>>> FILE = 'tmp/myfile.txt'
>>> FILE = '../myfile.txt'
7.1.2. Good Engineering 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
oros.getenv('PATH')
)>>> FILE = 'myfile.txt'
>>> FILES = [ ... 'myfile.txt', ... 'myfile.csv']
7.1.3. Raw Strings¶
Always use raw-strings (
r"..."
) for pathsEscapes does not matters
>>> print(r'C:\Users\Admin\file.txt') C:\Users\Admin\file.txt
>>> print('C:\\Users\\Admin\\file.txt') C:\Users\Admin\file.txt
>>> print('C:\Users\Admin\file.txt') Traceback (most recent call last): SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated \UXXXXXXXX escape
Problem:
\Users
after
\U...
python expects Unicode codepoint in hex i.e. 'U0001F680' which is 🚀 emoticons
is invalid hexadecimal characterOnly valid characters are
0123456789abcdefABCDEF
>>> import string >>> >>> >>> print(string.hexdigits) 0123456789abcdefABCDEF
7.1.4. Absolute Path¶
Absolute path on Windows starts with drive letter
Absolute path on
*nix
starts with root/
dirAbsolute path include all entries in the directories hierarchy
>>> FILE = r'C:\Users\Watney\myfile.txt'
>>> FILE = r'/tmp/myfile.txt'
7.1.5. Relative Path¶
Path is relative to currently running script
.
- Current directory..
- Parent directory
>>> FILE = r'myfile.txt'
>>> FILE = r'./myfile.txt'
>>> FILE = r'tmp/myfile.txt'
>>> FILE = r'./tmp/myfile.txt'
>>> FILE = r'../myfile.txt'
>>> FILE = r'../tmp/myfile.txt'
>>> FILE = r'../../myfile.txt'
>>> FILE = r'../../tmp/myfile.txt'
7.1.6. Escaping Characters in Path¶
"\ " (backslash space) - escapes space
Note that in Python escapes in paths are not required
>>> FILE = '/tmp/my file.txt'
>>> FILE = r'/tmp/my file.txt'
>>> FILE = r'C:\Users\Admin\myfile.txt' >>> >>> >>> repr(FILE) "'C:\\\\Users\\\\Admin\\\\myfile.txt'" >>> >>> str(FILE) 'C:\\Users\\Admin\\myfile.txt' >>> >>> print(repr(FILE)) 'C:\\Users\\Admin\\myfile.txt' >>> >>> print(FILE) C:\Users\Admin\myfile.txt
7.1.7. Exception Handling¶
>>> try:
... file = open('/tmp/myfile.txt')
... except FileNotFoundError:
... print('Sorry, file not found')
... except PermissionError:
... print('Sorry, not permitted')
Sorry, file not found
7.1.8. Create Directories¶
>>> from pathlib import Path
>>>
>>> Path('/tmp/a').mkdir()
>>> from pathlib import Path
>>>
>>> Path('/tmp/a').mkdir()
Traceback (most recent call last):
FileExistsError: [Errno 17] File exists: '/tmp/a'
>>> from pathlib import Path
>>>
>>> Path('/tmp/a').mkdir(exist_ok=True)
>>> from pathlib import Path
>>>
>>> Path('/tmp/a/b/c').mkdir(parents=True, exist_ok=True)
7.1.9. Touch File¶
>>> from pathlib import Path
>>>
>>> Path('/tmp/myfile.txt').touch()
7.1.10. Exists and is Directory or File¶
>>> from pathlib import Path
>>>
>>> Path('/tmp/myfile.txt').exists()
True
>>> from pathlib import Path
>>>
>>> Path('/tmp/myfile.txt').is_dir()
False
>>> from pathlib import Path
>>>
>>> Path('/tmp/myfile.txt').is_file()
True
7.1.11. Delete directory¶
Works only with empty directories:
>>> from pathlib import Path
>>>
>>> Path('/tmp/a').rmdir()
Traceback (most recent call last):
OSError: [Errno 66] Directory not empty: '/tmp/a'
Remove directories with files:
>>> from shutil import rmtree
>>>
>>> rmtree('/tmp/a', ignore_errors=True)
7.1.12. Current Working Directory¶
Returns an absolute path to current working directory
>>> from pathlib import Path >>> >>> # doctest: +SKIP ... Path.cwd() PosixPath('/home/python/')
7.1.13. Convert Relative Path to Absolute¶
>>> from pathlib import Path
>>>
>>> # doctest: +SKIP
... Path(Path.cwd(), 'myfile.txt')
PosixPath('/home/python/myfile.txt')
7.1.14. Script Path¶
Returns an absolute path to currently running script
>>> print(__file__) # doctest: +SKIP /home/python/myscript.py
7.1.15. Assignments¶
"""
* Assignment: File Path Exception
* Filename: file_path_exception.py
* Complexity: easy
* Lines of code: 6 lines
* Time: 3 min
English:
1. Using `input()` ask user for a file path
3. Handle exception for not existing file
4. Handle exception for not having sufficient permissions
Polish:
1. Używając `input()` zapytaj użytkownika o ścieżkę do pliku
3. Obsłuż wyjątek dla nieistniejącego pliku
4. Obsłuż wyjątek dla braku wystarczających uprawnień
Tests:
TODO: Doctests
TODO: Input Stub
"""
# Given
filename = input('Type filename: ')
"""
* Assignment: File Path Abspath
* Filename: file_path_abspath.py
* Complexity: easy
* Lines of code: 3 lines
* Time: 5 min
English:
1. Define `path` with converted `filename` to absolute path
2. Print if path exists and leads to file or directory
3. Compare result with "Tests" section (see below)
Polish:
1. Zdefiniuj `path` z przekonwertowym `filename` do ścieżki bezwzględnej
2. Wypisz czy ścieżka istnieje i czy prowadzi do pliku czy katalogu
3. Porównaj wyniki z sekcją "Tests" (patrz poniżej)
Tests:
TODO: Input Stub
>>> isinstance(result, Path)
True
>>> current_directory = Path.cwd()
>>> str(current_directory) in str(result)
True
"""
# Given
from pathlib import Path
filename = 'myfile.txt'
path = ...
result = ...