📦 Репозиторий занятия 50

Урок 50. Работа с файловой системой

Как работать с репозиторием

Каждая карточка говорит, о чём файл, что он выводит и что в нём искать. Код виден прямо здесь: его можно скопировать одной кнопкой, скачать файл или открыть его целиком.

Маршрут изучения

  1. Прочитайте описание: по нему уже понятно, о чём файл и что он выведет.
  2. Предскажите вывод: сравните своё предположение со строкой «Что выводит».
  3. Запустите: скачайте файл или скопируйте код кнопкой и выполните его у себя.
  4. Измените: поменяйте одно условие или значение и объясните новый результат.

Файлы: рекомендуемый порядок

1
MarkdownРазбор концепции38 строк

Абсолютные и относительные пути: разница и примеры для Windows/Linux

less_26__file_system/theory_01__absolute_and_relative.md

Определяет абсолютный путь как путь от корня файловой системы (однозначный, не зависит от текущей директории) и относительный — как путь, отсчитываемый от текущей рабочей директории запущенной программы. Показывает три сценария относительного пути: файл рядом со скриптом, файл во вложенной папке и переход в родительскую директорию через «../».

  • Абсолютный путь на Windows: "C:\\Users\\User\\Documents\\project\\data.txt"
  • Абсолютный путь на Linux/Mac: "/home/user/project/data.txt"
  • Относительный путь в той же папке: "data.txt"
  • Относительный путь во вложенной папке: "folder/data.txt"
  • Переход в родительскую папку: "../data.txt"
Показать начало файла (38 строк всего)
### Абсолютный путь

**Абсолютный путь** — это путь к файлу или папке, который начинается **от корня файловой системы**.  
Он всегда однозначно указывает, где находится файл.

**Пример (Windows):**

```python
path = "C:\\Users\\User\\Documents\\project\\data.txt"
```

**Пример (Linux / Mac):**

```python
path = "/home/user/project/data.txt"
```

### Относительный путь

**Относительный путь** — это путь **относительно текущей рабочей директории программы** (т.е. места, где запущен скрипт).

* Если файл лежит в той же папке, что и программа:

```python
file = "data.txt"
```

* Если файл лежит на уровень ниже (в другой папку внутри текущей директории):

```python
file = "folder/data.txt"
```

* Если нужно подняться на уровень выше:

```python
file = "../data.txt"      # ../ означает 'выйти в родительскую папку'
```
Проверьте себя: Если скрипт запустить из другой рабочей директории (не из папки со скриптом), как это повлияет на относительный путь "data.txt"?
2
MarkdownРазбор концепции32 строк

Справочная таблица методов os и os.path + отличие mkdir от makedirs

less_26__file_system/theory_02__os_methods.md

Сводная таблица основных функций модуля os для работы с файловой системой — от os.getcwd() и os.listdir() до os.path.join(), os.path.split() и os.path.basename()/dirname() — с примером вызова и ожидаемым результатом для каждой. Отдельная таблица сравнивает os.mkdir() и os.makedirs() по трём критериям: создание вложенных папок, поведение при существующей папке (exist_ok) и генерация FileExistsError.

  • Таблица методов: getcwd, chdir, listdir, mkdir, makedirs, rmdir, remove, rename
  • Таблица методов os.path: abspath, exists, isdir, isfile, join, split, basename, dirname
  • os.sep — разделитель путей, зависящий от ОС
  • Сравнительная таблица mkdir vs makedirs: вложенность, exist_ok, FileExistsError
Показать начало файла (32 строк всего)
## Основные методы модуля `os`

| Метод                     | Назначение                                  | Пример                                      | Ожидаемый результат                                       |
|---------------------------|---------------------------------------------|---------------------------------------------|-----------------------------------------------------------|
| `os.getcwd()`             | Возвращает текущую рабочую директорию       | `print(os.getcwd())`                        | Например: `C:\Users\User\project`                         |
| `os.chdir(path)`          | Меняет текущую рабочую директорию           | `os.chdir("folder")`                        | Текущая директория становится `folder`                    |
| `os.listdir(path)`        | Возвращает список файлов/папок в директории | `print(os.listdir("."))`                    | `['main.py', 'data', 'readme.txt']`                       |
| `os.mkdir(path)`          | Создаёт папку (1 уровень)                   | `os.mkdir("new_folder")`                    | Создаст каталог `new_folder`                              |
| `os.makedirs(path)`       | Создаёт вложенные папки                     | `os.makedirs("a/b/c")`                      | Создаст каталоги `a`, `a/b`, `a/b/c`                      |
| `os.rmdir(path)`          | Удаляет **пустую** папку                    | `os.rmdir("new_folder")`                    | Папка удаляется, если она пуста                           |
| `os.remove(path)`         | Удаляет файл                                | `os.remove("file.txt")`                     | Файл будет удалён                                         |
| `os.rename(src, dst)`     | Переименовывает файл или папку              | `os.rename("old.txt", "new.txt")`           | `old.txt` → `new.txt`                                     |
| `os.path.abspath(path)`   | Возвращает абсолютный путь                  | `print(os.path.abspath("data.txt"))`        | Например: `C:\Users\User\project\data.txt`                |
| `os.path.exists(path)`    | Проверяет существование пути                | `print(os.path.exists("data.txt"))`         | `True` или `False`                                        |
| `os.path.isdir(path)`     | Проверяет, является ли путь папкой          | `print(os.path.isdir("docs"))`              | `True` / `False`                                          |
| `os.path.isfile(path)`    | Проверяет, является ли путь файлом          | `print(os.path.isfile("main.py"))`          | `True` / `False`                                          |
| `os.path.join(a, b, ...)` | Правильно соединяет части пути              | `print(os.path.join("folder", "file.txt"))` | `folder/file.txt` (Linux) или `folder\file.txt` (Windows) |
| `os.sep`                  | Символ разделителя путей OS (зависит от ОС) | `print(os.sep)`                             | `/` (Linux/Mac) или `\` (Windows)                         |
| `os.path.split(path)`    | Разделяет путь на директорию и имя файла     | `os.path.split("folder/file.txt")`          | `('folder', 'file.txt')`               |
| `os.path.basename(path)` | Возвращает только имя файла или папки        | `os.path.basename("folder/file.txt")`       | `'file.txt'`                           |
| `os.path.dirname(path)`  | Возвращает только директорию без имени файла | `os.path.dirname("folder/file.txt")`        | `'folder'`                             |


## Отличие `os.mkdir` от `os.makedirs`

| Возможности                                        | Пример                                  | `os.mkdir` | `os.makedirs`             |
|----------------------------------------------------|-----------------------------------------| ---------- | ------------------------- |
| Может создать ТОЛЬКО одну вложенную папку          | `os.mkdir('folder1')`                   | ✅          | ❌                         |
| Может создавать вложенные папки                    | `os.makedirs('a/b/c')`                  | ❌          | ✅                         |
| Может не выбрасывать ошибку, если папка существует | `os.makedirs('folder2', exist_ok=True)` | ❌          | ✅ (`exist_ok=True`)       |
| Генерирует `FileExistsError`, если папка уже есть  | `os.mkdir('folder1')`                   | ✅          | ✅ (если `exist_ok=False`) |
Проверьте себя: Почему os.path.join() предпочтительнее ручной конкатенации строк вроде folder + "/" + file при работе с путями на разных ОС?
3
PythonИсполняемый пример42 строк

os.walk(): рекурсивный обход дерева каталогов с отступами

less_26__file_system/theory_03__os_walk.py

Реализует функцию print_tree(), которая обходит директорию рекурсивно через os.walk() и печатает дерево файлов и папок с отступами по уровню вложенности, сортируя файлы и подпапки для аккуратного порядка. Уровень вложенности вычисляется через подсчёт разделителей os.sep в пути root после отбрасывания start_path. В конце файла закомментированный пример реального вывода на структуре папки урока — как выглядит результат на настоящем дереве.

  • print_tree(start_path=".") — обход через os.walk(start_path)
  • level = root.replace(start_path, "").count(os.sep) — глубина вложенности
  • files = sorted(files); dirs[:] = sorted(dirs) — сортировка для порядка обхода
  • branch = "└──" if is_last else "├──" — визуальное дерево, похожее на tree
  • print_tree(".") — запуск от текущей рабочей директории
  • Закомментированный блок — пример реального вывода на структуре папки урока

Что выводит: Запуск из отдельной scratchpad-копии (сам файл + подпапка demo/inside.txt) дал дерево: «├── [.]», «│ ├── theory_03__os_walk.py», «│ ├── [demo]», «│ │ └── inside.txt» — то есть функция обходит ТЕКУЩУЮ рабочую директорию запуска (start_path="."), а не саму папку урока в репозитории.

Начало файла
"""
os.walk - удобная рекурсивная функция, которая сама рекурсивно
обходит все директории, начиная от текущей
"""
import os

def print_tree(start_path="."):
    for root, dirs, files in os.walk(start_path):
        level = root.replace(start_path, "").count(os.sep)
        indent = "│   " * level
        folder_name = os.path.basename(root) if os.path.basename(root) else root
        print(f"{indent}├── [{folder_name}]")

        # Сортируем, чтобы порядок был аккуратный
Показать файл целиком (42 строк)
"""
os.walk - удобная рекурсивная функция, которая сама рекурсивно
обходит все директории, начиная от текущей
"""
import os

def print_tree(start_path="."):
    for root, dirs, files in os.walk(start_path):
        level = root.replace(start_path, "").count(os.sep)
        indent = "│   " * level
        folder_name = os.path.basename(root) if os.path.basename(root) else root
        print(f"{indent}├── [{folder_name}]")

        # Сортируем, чтобы порядок был аккуратный
        files = sorted(files)
        dirs[:] = sorted(dirs)

        for i, file in enumerate(files):
            is_last = (i == len(files) - 1 and not dirs)  # последний только если нет подпапок ниже
            sub_indent = "│   " * (level + 1)
            branch = "└──" if is_last else "├──"
            print(f"{sub_indent}{branch} {file}")

print_tree(".")

#
# ├── [.]
# │   ├── homework_33_01.py
# │   ├── homework_33_02.py
# │   ├── homework_36_03.py
# │   ├── practice_work_35_01.py
# │   ├── practice_work_35_02.py
# │   ├── practice_work_03.py
# │   ├── theory_01__absolute_and_relative.md
# │   ├── theory_02__os_methods.md
# │   ├── theory_03__os_walk.py
# │   ├── theory_04__sys_argv.py
# │   ├── theory_05__PRACTICE_getting_parameters_in_endpoints.md
# │   ├── [project]
# │   │   ├── homework_33_01.py
# │   │   ├── homework_33_02.py
# │   │   └── homework_36_03.py
Проверьте себя: Что нужно изменить в вызове print_tree(), чтобы построить дерево не текущей рабочей директории, а произвольной папки, переданной как аргумент?
Открыть файл →
4
ФайлМатериал репозитория7 строк

Поиск файлов по расширению через os.walk() (файл без расширения .py)

less_26__file_system/theory_04__find_file_with_extension

Короткий скрипт из четырёх строк логики: рекурсивно обходит текущую директорию через os.walk() и печатает путь к каждому файлу, оканчивающемуся на «.txt». Несмотря на то что у самого файла в репозитории отсутствует расширение .py, содержимое — обычный исполняемый Python-код в кодировке UTF-8 с переносами строк CRLF.

  • for root, dirs, files in os.walk(".") — обход текущей рабочей директории
  • file.endswith(".txt") — фильтр только по расширению .txt
  • os.path.join(root, file) — собирает полный относительный путь к найденному файлу

Что выводит: Запуск из scratchpad-копии, где рядом лежит sample.txt, дал: «Найден файл: .\sample.txt» — путь построен через os.path.join и использует разделитель ОС (обратный слэш на Windows).

Показать начало файла (7 строк всего)
import os

# Поиск всех .txt файлов
for root, dirs, files in os.walk("."):
    for file in files:
        if file.endswith(".txt"):
            print(f"Найден файл: {os.path.join(root, file)}")
Проверьте себя: Как изменить условие file.endswith(".txt"), чтобы скрипт искал файлы сразу с несколькими расширениями, например .txt и .md?
5
MarkdownРазбор концепции60 строк

Функция open(): режимы файла и работа через контекстный менеджер with

less_26__file_system/theory_05__open.md

Описывает сигнатуру open(filename, mode, encoding) и таблицу режимов открытия файла — r, w, a, x, b, t, + — с кратким назначением каждого. Показывает два базовых сценария: чтение с явным file.close() и запись в файл, а затем подчёркивает, что конструкция with автоматически закрывает файл и потому предпочтительнее ручного close().

  • open(filename, mode='r', encoding=None) — сигнатура функции
  • Таблица режимов: r, w, a, x, b, t, +
  • Пример чтения: file.read() + обязательный file.close()
  • Пример записи: file.write() + file.close()
  • with open(...) as file: — автоматическое закрытие файла
Показать начало файла (60 строк всего)
## Функция `open()` 

Используется для открытия файлов и работы с ними: 
* чтения, 
* записи, 
* добавления данных

### Синтаксис

```python
open(filename, mode='r', encoding=None)
```

### Параметры

* `filename` — путь к файлу.
* `mode` — режим открытия файла.
* `encoding` — кодировка файла (обычно `utf-8` для текстовых файлов).

### Основные режимы открытия

| Режим | Описание                                               |
| ----- | ------------------------------------------------------ |
| `r`   | Чтение файла (по умолчанию)                            |
| `w`   | Запись (создаёт новый файл или очищает существующий)   |
| `a`   | Добавление данных в конец файла                        |
| `x`   | Создание нового файла, ошибка если файл уже существует |
| `b`   | Бинарный режим                                         |
| `t`   | Текстовый режим (по умолчанию)                         |
| `+`   | Чтение и запись одновременно                           |

### Пример чтения файла

```python
file = open("data.txt", "r", encoding="utf-8")
text = file.read()
file.close()  # ⚠️ Открытый файл ОБЯЗАТЕЛЬНО должен быть закрыт

print(text)
```

### Пример записи в файл

```python
file = open("data.txt", "w", encoding="utf-8")
file.write("Привет, мир!")
file.close()
```

### Контекстный менеджер

Конструкция `with` автоматически закрывает файл после завершения работы.

```python
with open("data.txt", "r", encoding="utf-8") as file:
    text = file.read()

print(text)
```
Проверьте себя: Что произойдёт с данными, если открыть существующий файл в режиме 'w' вместо 'a' для дозаписи?
6
PythonИсполняемый пример20 строк

sys.argv: аргументы командной строки, переданные скрипту

less_26__file_system/theory_06__sys_argv.py

Показывает, что sys.argv — это список строк, где нулевой элемент всегда имя запущенного скрипта, а начиная с первого — аргументы, переданные при запуске из терминала. В докстринге дан пример команды запуска с пятью аргументами. Файл написан без проверки на пустой sys.argv[1:], поэтому запуск без аргументов не падает — просто цикл проходит по пустому списку.

  • Докстринг — объяснение sys.argv[0] и sys.argv[1:], пример команды запуска
  • sys.argv[0] — имя скрипта
  • for i, value in enumerate(sys.argv[1:]) — перебор переданных аргументов
  • type(value) — все аргументы командной строки приходят строками (str)

Что выводит: Запуск без аргументов («python theory_06__sys_argv.py») не вызывает ошибку — печатается только «Имя скрипта: theory_06__sys_argv.py» и заголовок «Все переданные аргументы:», цикл не выполняется ни разу. Запуск «python theory_06__sys_argv.py alpha beta gamma» дополнительно печатает три строки: «1. alpha <class 'str'>», «2. beta <class 'str'>», «3. gamma <class 'str'>».

Начало файла
"""
sys.argv`— это список аргументов, которые были переданы скрипту при запуске из командной строки.

- Первый элемент (`sys.argv[0]`) - всегда содержит имя скрипта.
- Все последующие элементы (`sys.argv[1:]`) — это аргументы, переданные в командной строке


КОМАНДА ДЛЯ ПРИМЕРА:

python theory_06__sys_argv.py аргумент_1 второй третий 4-й и 5

"""

import sys
Показать файл целиком (20 строк)
"""
sys.argv`— это список аргументов, которые были переданы скрипту при запуске из командной строки.

- Первый элемент (`sys.argv[0]`) - всегда содержит имя скрипта.
- Все последующие элементы (`sys.argv[1:]`) — это аргументы, переданные в командной строке


КОМАНДА ДЛЯ ПРИМЕРА:

python theory_06__sys_argv.py аргумент_1 второй третий 4-й и 5

"""

import sys

print("Имя скрипта:", sys.argv[0])

print("Все переданные аргументы:")
for i, value in enumerate(sys.argv[1:]):
    print(f"{i+1}. {value} {type(value)}")
Проверьте себя: Почему все значения в sys.argv имеют тип str, даже если передать число, например "5" — и что нужно сделать, чтобы использовать его как int?
Открыть файл →