17.3. Pathlib Files

17.3.1. SetUp

>>> from pathlib import Path

17.3.2. Define Path

>>> myfile = Path('/tmp/myfile.txt')

17.3.3. Touch

  • If file does not exist, it will be created.

  • If file exists, it will update the last modified time.

>>> myfile.touch()

17.3.4. Is File

>>> myfile.is_file()
True

17.3.5. Write Text

>>> myfile.write_text('Hello World')
11
>>> myfile.write_text('Hello World', encoding='utf-8')
11

17.3.6. Read Text

>>> result = myfile.read_text()
>>> result
'Hello World'
>>> result = myfile.read_text(encoding='utf-8')
>>> result
'Hello World'

17.3.7. Name

>>> myfile.name
'myfile.txt'

17.3.8. Stem

>>> myfile.stem
'myfile'

17.3.9. Suffix

>>> myfile.suffix
'.txt'

17.3.10. Suffixes

>>> myfile.suffixes
['.txt']

17.3.11. Parent

>>> myfile.parent
PosixPath('/tmp')

17.3.12. Parents

>>> list(myfile.parents)
[PosixPath('/tmp'), PosixPath('/')]

17.3.13. Glob

SetUp:

>>> mydir = Path('/tmp/mydir/')
>>> mydir.mkdir(exist_ok=True)
>>> (mydir / 'myfile1.md').touch()
>>> (mydir / 'myfile2.md').touch()
>>> mydir.glob('*.md')
<map object at 0x...>

17.3.14. RGlob

17.3.15. Glob and Rglob

SetUp:

>>> mydir = Path('/tmp/mydir/')
>>> mydir.mkdir(exist_ok=True)
>>> (mydir / 'myfile1.md').touch()
>>> (mydir / 'myfile2.md').touch()

Usage:

>>> mydir.glob('*.md')
<map object at 0x...>
>>>
>>> sorted(mydir.glob('*.md'))
[PosixPath('/tmp/mydir/myfile1.md'), PosixPath('/tmp/mydir/myfile2.md')]
>>> sorted(mydir.rglob('*.md'))
[PosixPath('/tmp/mydir/myfile1.md'), PosixPath('/tmp/mydir/myfile2.md')]

17.3.16. Join Paths

>>> mydir = Path('/tmp/mydir/')
>>> myfile = mydir / 'myfile.txt'
>>> myfile = Path('/')
>>> myfile /= 'tmp'
>>> myfile /= 'mydir'
>>> myfile /= 'myfile.txt'

17.3.17. Stat

$ stat -r /tmp/mydir/myfile.txt
16777234 74991501 0100644 1 501 0 0 23 1739435370 1739435370 1739435522 1739434616 4096 8 64 /tmp/mydirectory/myfile.txt
$ stat /tmp/mydir/myfile.txt
16777234 74991501 -rw-r--r-- 1 matt wheel 0 23 "Feb 13 09:29:30 2025" "Feb 13 09:29:30 2025" "Feb 13 09:32:02 2025" "Feb 13 09:16:56 2025" 4096 8 0x40 /tmp/mydirectory/myfile.txt
>>> myfile = Path('/tmp/mydir/myfile.txt')
>>> myfile.stat()
os.stat_result(st_mode=33188, st_ino=73966028, st_dev=16777234, st_nlink=1, st_uid=501, st_gid=20, st_size=8965, st_atime=1739174544, st_mtime=1739174544, st_ctime=1739174544)
>>> oct(33188)
'0o100644'
>>> from datetime import datetime, timezone
>>>
>>> datetime.fromtimestamp(1739174544, tz=timezone.utc)
datetime.datetime(2025, 2, 10, 8, 2, 24, tzinfo=datetime.timezone.utc)

17.3.18. Use Case - 1

>>> FILE = '/tmp/mydir/myfile.txt'
>>> with open(FILE) as file:
...     content = file.read()
>>> FILE = Path('/tmp/mydir/myfile.txt')
>>> with open(FILE) as file:
...     content = file.read()
>>> file = Path('/tmp/mydir/myfile.txt')
>>> result = file.read_text()

17.3.19. Use Case - 1

>>> from itertools import chain
>>>
>>>
>>> mydir = Path('/tmp/mydir')
>>> files = chain(
...     mydir.rglob('*.md'),
...     mydir.rglob('*.html'),
... )
>>>
>>> for file in sorted(files):
...     print(file)
...
/tmp/mydir/myfile1.md
/tmp/mydir/myfile2.md

17.3.20. Use Case - 2

>>> directories = [
...     '/tmp/mydir',
...     '/tmp/newdir',
...     '/tmp/otherdir',
... ]
>>> for directory in map(Path, directories):
...     print(directory.exists())
...
True
False
False
>>> for directory in map(Path, directories):
...     for file in directory.rglob('*.txt'):
...         print(file)
...
/tmp/mydir/myfile.txt

17.3.21. Use Case - 3

>>> directories = [
...     Path('/tmp/mydir'),
...     Path('/tmp/newdir'),
...     Path('/tmp/otherdir'),
... ]
>>>
>>> for directory in directories:
...     directory.exists()
...
True
False
False

17.3.22. Assignments

# FIXME: exists()
# FIXME: is_file()
# FIXME: is_dir()
# FIXME: is_symlink()

# %% About
# - Name: File Path Abspath
# - Difficulty: easy
# - Lines: 3
# - Minutes: 5

# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author

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

# %% Polish
# 1. Zdefiniuj `abspath` z przekonwertowanym `filename` do ścieżki bezwzględnej
# 2. Do `result` przypisz ciąg znaków:
#    - `file` jeżeli ścieżka jest plikiem
#    - `directory` jeżeli ścieżka jest katalogiem
#    - `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()`

# %% Doctests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'

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

>>> 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'
"""

# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -f -v myfile.py`

# %% Imports
from pathlib import Path

# %% Types
abspath: Path
result: str

# %% Data
FILENAME = 'myfile.txt'

# %% Result
abspath = ...
result = ...