`pathlib` предоставляет класс `Path` — объектно-ориентированный способ работы с путями файловой системы. Он заменяет строковые манипуляции `os.path` чистым, читабельным доступом к атрибутам.
```python
from pathlib import Path
```
## Создание Path-объектов
```python
p = Path("/home/user/documents/report.txt")
p = Path(".") # текущая директория
p = Path.home() # домашняя директория: /home/user
p = Path.cwd() # текущая рабочая директория
# Пути Windows тоже работают:
p = Path("C:/Users/Alice/Desktop/file.txt")
```
## Атрибуты Path
```python
p = Path("/home/user/projects/script.py")
print(p.name) # "script.py" — имя файла с расширением
print(p.stem) # "script" — имя файла без расширения
print(p.suffix) # ".py" — расширение с точкой
print(p.suffixes) # [".py"] — все расширения (для ".tar.gz" → [".tar", ".gz"])
print(p.parent) # /home/user/projects — родительская директория
print(p.parts) # ("/", "home", "user", "projects", "script.py")
print(p.root) # "/"
```
## Объединение путей
Используйте оператор `/` — намного чище чем `os.path.join`:
```python
base = Path("/home/user")
config = base / "config" / "settings.json"
print(config) # /home/user/config/settings.json
# Справа можно передавать строки
reports = base / "reports"
report_file = reports / "2024" / "q1.csv"
```
## Проверка существования
```python
p = Path("/home/user/data.txt")
print(p.exists()) # True/False — файл или директория существует
print(p.is_file()) # True если существует и является обычным файлом
print(p.is_dir()) # True если существует и является директорией
print(p.is_symlink()) # True если является символической ссылкой
```
## Конвертация и сравнение
```python
p = Path("/home/user/file.txt")
# Преобразование в строку
str(p) # "/home/user/file.txt"
p.as_posix() # "/home/user/file.txt" — всегда косые черты
# Абсолютный путь
p.resolve() # разрешает символические ссылки, возвращает абсолютный Path
# Относительный путь
p.relative_to("/home/user") # Path("file.txt")
```
## Чтение и запись файлов
Объекты `Path` могут читать и записывать текст и байты напрямую — для простых случаев `open()` не нужен:
```python
from pathlib import Path
p = Path("notes.txt")
# Запись текста
p.write_text("Hello, pathlib!\n", encoding="utf-8")
# Чтение текста
content = p.read_text(encoding="utf-8")
print(content) # Hello, pathlib!
# Чтение байтов
data = p.read_bytes()
# Запись байтов
p.write_bytes(b"\x00\x01\x02")
```
Для чтения строка за строкой используйте `open()` с Path:
```python
with p.open("r", encoding="utf-8") as f:
for line in f:
print(line.strip())
```
## Просмотр содержимого директории
```python
d = Path("/home/user/projects")
# Все записи (файлы и поддиректории)
for item in d.iterdir():
print(item.name, "dir" if item.is_dir() else "file")
# Только файлы
files = [f for f in d.iterdir() if f.is_file()]
# Только директории
subdirs = [f for f in d.iterdir() if f.is_dir()]
```
## glob: поиск по паттерну
```python
src = Path("/home/user/projects")
# Все Python-файлы в директории (без рекурсии)
py_files = list(src.glob("*.py"))
# Все Python-файлы рекурсивно (** = любое количество директорий)
all_py = list(src.rglob("*.py"))
# Все лог-файлы в любой поддиректории "logs"
logs = list(src.glob("**/logs/*.log"))
```
## Создание директорий
```python
new_dir = Path("/home/user/projects/new_feature")
# Создать одну директорию
new_dir.mkdir()
# Создать родительские директории если не существуют, без ошибки если уже есть
new_dir.mkdir(parents=True, exist_ok=True)
```
## Переименование и удаление
```python
p = Path("old_name.txt")
# Переименовать (возвращает новый Path)
new_p = p.rename("new_name.txt")
print(new_p) # new_name.txt
# Удалить файл
p.unlink()
# Удалить пустую директорию
d = Path("empty_dir")
d.rmdir()
# Python 3.8+: missing_ok
p.unlink(missing_ok=True) # без ошибки если не найден
```
## Практический пример: обработать все CSV-файлы
```python
data_dir = Path("data")
output_dir = Path("output")
output_dir.mkdir(exist_ok=True)
for csv_file in data_dir.glob("*.csv"):
content = csv_file.read_text()
processed = content.upper() # условная трансформация
out_file = output_dir / csv_file.name
out_file.write_text(processed)
print(f"Обработано: {csv_file.name}")
```
## Атрибуты Path (только для чтения)
| Атрибут | Пример значения | Что возвращает |
|---|---|---|
| `p.name` | `"script.py"` | Имя файла с расширением |
| `p.stem` | `"script"` | Имя файла без расширения |
| `p.suffix` | `".py"` | Последнее расширение (с точкой) |
| `p.suffixes` | `[".tar", ".gz"]` | Все расширения |
| `p.parent` | `Path("/home/user")` | Path родительской директории |
| `p.parents` | (итерируемый) | Все родительские директории |
| `p.parts` | `("/", "home", "user", "f.py")` | Кортеж компонентов пути |
| `p.root` | `"/"` | Корневой компонент |
## Методы Path — запросы
| Метод | Что делает |
|---|---|
| `p.exists()` | True если путь существует (файл или директория) |
| `p.is_file()` | True если существует и является обычным файлом |
| `p.is_dir()` | True если существует и является директорией |
| `p.is_symlink()` | True если символическая ссылка |
| `p.stat()` | os.stat_result (размер, mtime и т.д.) |
| `p.resolve()` | Абсолютный путь с разрешёнными ссылками |
| `p.relative_to(other)` | Относительный путь от `other` |
| `p.with_name(name)` | Новый путь с другим именем |
| `p.with_stem(stem)` | Новый путь с другим stem |
| `p.with_suffix(suf)` | Новый путь с другим расширением |
## Методы Path — файловый ввод/вывод
| Метод | Что делает |
|---|---|
| `p.read_text(encoding=...)` | Прочитать содержимое как str |
| `p.write_text(s, encoding=...)` | Записать str |
| `p.read_bytes()` | Прочитать содержимое как bytes |
| `p.write_bytes(b)` | Записать bytes |
| `p.open(mode, encoding=...)` | Открыть файловый объект |
## Методы Path — операции с ФС
| Метод | Что делает |
|---|---|
| `p.mkdir(parents=False, exist_ok=False)` | Создать директорию |
| `p.rename(target)` | Переименовать, вернуть новый Path |
| `p.replace(target)` | Переименовать, перезаписать если есть |
| `p.unlink(missing_ok=False)` | Удалить файл или ссылку |
| `p.rmdir()` | Удалить пустую директорию |
| `p.touch()` | Создать пустой файл или обновить mtime |
| `p.iterdir()` | Итерировать по содержимому директории |
| `p.glob(pattern)` | Найти файлы по паттерну |
| `p.rglob(pattern)` | Рекурсивный glob |
## Паттерны glob
| Паттерн | Что соответствует |
|---|---|
| `*` | Любое имя в текущей директории |
| `*.py` | Python-файлы в текущей директории |
| `**/*.py` | Python-файлы рекурсивно |
| `??.txt` | Двухсимвольное имя + .txt |
Имея строку пути `"/home/user/projects/data/report_2024.csv"`, создайте объект `Path` из неё и выведите:
- Полное имя файла (`name`)
- Имя без расширения (`stem`)
- Расширение (`suffix`)
- Родительскую директорию (`parent`)
- Все компоненты пути (`parts`)
from pathlib import Path
p = Path("/home/user/projects/data/report_2024.csv")
# Выведите: name, stem, suffix, parent, parts
print(p.name) # ???
print(p.stem) # ???
print(p.suffix) # ???
print(p.parent) # ???
print(p.parts) # ???
Напишите функцию `build_path(base, *parts)`, которая принимает базовую директорию как строку и любое количество частей пути, соединяет их через оператор `/` и возвращает итоговый объект `Path`. Пример: `build_path("/home/user", "projects", "myapp", "config.json")` → `Path("/home/user/projects/myapp/config.json")`.
from pathlib import Path
def build_path(base, *parts):
pass
result = build_path("/home/user", "projects", "myapp", "config.json")
print(result) # /home/user/projects/myapp/config.json
Решение
from pathlib import Path
def build_path(base, *parts):
p = Path(base)
for part in parts:
p = p / part
return p
# Короче: Path(base).joinpath(*parts)
result = build_path("/home/user", "projects", "myapp", "config.json")
print(result) # /home/user/projects/myapp/config.json
Напишите функцию `change_extension(path_str, new_ext)`, которая принимает строку пути и новое расширение (с точкой, например `".txt"`), и возвращает новый `Path` с изменённым расширением. Пример: `change_extension("/home/user/data.csv", ".json")` → `Path("/home/user/data.json")`. Используйте `p.with_suffix()`.
Напишите функцию `safe_read(path_str, encoding="utf-8")`, которая читает содержимое файла по `path_str` и возвращает его как строку. Если файл не существует — возвращает `None`. При любой другой ошибке — тоже `None`. Используйте `Path.read_text()`.
Напишите функцию `write_and_verify(path_str, content)`, которая:
1. Записывает `content` в файл по `path_str` через `Path.write_text()`
2. Читает обратно через `Path.read_text()`
3. Возвращает `True` если содержимое совпадает, `False` иначе
Используйте `encoding="utf-8"` для обеих операций.
Напишите функцию `count_by_extension(dir_path)`, которая принимает строку пути к директории и возвращает словарь, где каждое расширение файла соответствует количеству файлов с этим расширением в директории (без рекурсии). Пример: если директория содержит `a.py`, `b.py`, `c.txt`, `d.txt`, `e.md`, результат: `{".py": 2, ".txt": 2, ".md": 1}`.
from pathlib import Path
def count_by_extension(dir_path):
pass
# Пример: если в директории a.py, b.py, c.txt, d.txt, e.md
# результат: {".py": 2, ".txt": 2, ".md": 1}
Решение
from pathlib import Path
def count_by_extension(dir_path):
counts = {}
for p in Path(dir_path).iterdir():
if p.is_file():
ext = p.suffix
counts[ext] = counts.get(ext, 0) + 1
return counts
import tempfile
with tempfile.TemporaryDirectory() as d:
for name in ["a.py", "b.py", "c.txt", "d.txt", "e.md"]:
Path(d, name).write_text("", encoding="utf-8")
print(count_by_extension(d))
# {".py": 2, ".txt": 2, ".md": 1}
Напишите функцию `find_large_files(dir_path, min_size_bytes)`, которая рекурсивно ищет в директории все файлы больше `min_size_bytes` и возвращает их пути как отсортированный список объектов `Path`. Используйте `p.rglob("*")` и `p.stat().st_size`.
from pathlib import Path
def find_large_files(dir_path, min_size_bytes):
pass
# Возвращает отсортированный список Path-объектов для файлов > min_size_bytes
Решение
from pathlib import Path
def find_large_files(dir_path, min_size_bytes):
return sorted(
p for p in Path(dir_path).rglob("*")
if p.is_file() and p.stat().st_size > min_size_bytes
)
for f in find_large_files(".", 1000):
print(f)
Напишите функцию `ensure_dir(path_str)`, которая создаёт директорию по `path_str` если она не существует. Она должна:
- Создавать все промежуточные родительские директории по необходимости
- Не бросать ошибку если директория уже существует
- Возвращать объект `Path` директории
Используйте `Path.mkdir(parents=True, exist_ok=True)`.
from pathlib import Path
def ensure_dir(path_str):
pass
p = ensure_dir("/tmp/myapp/logs/2024")
print(p.is_dir()) # True
print(p) # /tmp/myapp/logs/2024
Решение
from pathlib import Path
def ensure_dir(path_str):
p = Path(path_str)
p.mkdir(parents=True, exist_ok=True)
return p
p = ensure_dir("/tmp/myapp/logs/2024")
print(p.is_dir()) # True
print(p) # /tmp/myapp/logs/2024
Напишите функцию `backup(path_str)`, которая создаёт резервную копию файла добавляя `.bak` к его имени. Если файл не существует — бросает `FileNotFoundError`. Возвращает `Path` резервного файла. Пример: `backup("/home/user/data.txt")` создаёт `/home/user/data.txt.bak` и возвращает этот путь.
from pathlib import Path
import shutil
def backup(path_str):
pass
Path("/tmp/data_original.txt").write_text("important", encoding="utf-8")
bak = backup("/tmp/data_original.txt")
print(bak) # /tmp/data_original.txt.bak
Решение
from pathlib import Path
import shutil
def backup(path_str):
p = Path(path_str)
if not p.exists():
raise FileNotFoundError(f"File not found: {p}")
bak = p.with_suffix(p.suffix + ".bak")
shutil.copy2(str(p), str(bak))
return bak
Path("/tmp/data_original.txt").write_text("important", encoding="utf-8")
bak = backup("/tmp/data_original.txt")
print(bak) # /tmp/data_original.txt.bak
print(bak.read_text(encoding="utf-8")) # important
Напишите функцию `find_python_files(start_dir)`, которая рекурсивно находит все файлы `.py` в `start_dir`, сортирует их по имени и возвращает список их относительных путей (относительно `start_dir`) как строки. Используйте `Path.rglob("*.py")` и `p.relative_to(start_dir)`.
from pathlib import Path
def find_python_files(start_dir):
pass
# Возвращает список относительных строк пути отсортированных по имени
for f in find_python_files("."):
print(f)
Решение
from pathlib import Path
def find_python_files(start_dir):
base = Path(start_dir)
return sorted(
str(p.relative_to(base))
for p in base.rglob("*.py")
)
for f in find_python_files("."):
print(f)
No split tab
Настройки cookies
Мы используем необходимые cookies для работы сайта. С вашего разрешения мы также можем сохранять настройки сайта и использовать аналитические и рекламные cookies, чтобы понимать использование сайта и поддерживать развитие проекта.
* Вы всегда можете изменить свой выбор в настройках сайта.
Выберите категории cookies
Настройки аналитики
Можно отключить аналитику использования платформы. Также можно отправить в Google Analytics запрос на удаление данных об использовании этого сайта, связанных с этим браузером.
Учебный workspace
Учитесь, читая, запуская код и решая задачи.
Практикуйте программирование с пояснениями тем, упражнениями, инструментами browser IDE, проверкой regex и тренировкой печати кода в одном workspace.
Открывайте инструменты во вкладках.Упражнения, IDE-инструменты и тренажеры остаются доступными как вкладки сайта.
Переключайтесь без потери контекста.Переходите между пояснениями, кодом и утилитами, сохраняя свое место.
Используйте sidebar как карту.Левые панели содержат навигацию, настройки, файлы, libraries и управление инструментами.
PythonJavaScriptSQLite
Одна IDE, три практичных режима
Python в браузере.Запускайте небольшие скрипты, пробуйте библиотеки и тренируйте API-запросы без установки.
JavaScript для быстрых экспериментов.Проверяйте код для браузера и сравнивайте идеи рядом с учебными материалами.
SQLite для практики с данными.Открывайте обозреватель базы данных, изучайте таблицы, пишите запросы и учитесь SQL локально.
ТемаIDE
Работайте рядом в split tabs
Держите инструкции перед глазами.Откройте упражнение или справочную страницу рядом с IDE, вместо постоянных переключений.
Сравнивайте инструменты во время обучения.Размещайте проверки regex, пояснения и эксперименты с кодом рядом, когда это нужно для задачи.
Закройте split, когда закончите.Workspace вернётся к одной сфокусированной вкладке, а открытые вкладки сайта останутся доступны.
Тренажер слепой печати кода
Или просто текста
Тренажер рассчитан на физическую клавиатуру.Откройте этот раздел на ноутбуке или компьютере с широким экраном. На телефоне тренировка слепой печати не будет корректной.
Скорость: 0 зн/мин
0 слов/мин
Лучшая скорость (60с): 0 зн/мин
0 слов/мин
Ошибки: 0
Общее время: 0.0 с
Для активации режима слепого набора не подсматривайте на физическую клавиатуру.