📋 Формулировка задания
Задание: напишите программу process_numbers.py, которая:
- Принимает путь к директории через аргумент командной строки.
- Проверяет, что директория существует. Если нет — выводит сообщение и завершает работу.
- Рекурсивно ищет файлы с именем
numbers.txt. - Читает каждый файл и суммирует числа построчно. Пустые строки игнорируются.
- Обрабатывает ошибки: файл не найден, некорректное число, проблемы с кодировкой.
- Записывает результат в файл
summary.txtв текущей директории. - Логирует ошибки в файл
processing.log.
Пример запуска:
python process_numbers.py /home/user/data
Пример файла numbers.txt:
10
20
abc
30
Пример результата в summary.txt:
/home/user/data/project1/numbers.txt: 60
/home/user/data/project2/numbers.txt: 15
🛠️ Пошаговое решение
1
Импортируйте нужные модули и настройте логирование
import logging
import os
import sys
logging.basicConfig(
filename="processing.log",
format="%(asctime)s - %(levelname)s - %(message)s",
level=logging.ERROR,
)
2
Проверьте аргументы командной строки
if len(sys.argv) != 2:
print("Использование: python process_numbers.py <директория>")
sys.exit(1)
source_dir = sys.argv[1]
if not os.path.isdir(source_dir):
print(f"Ошибка: директория '{source_dir}' не существует.")
sys.exit(1)
3
Найдите все файлы numbers.txt
def find_numbers_files(directory: str) -> list[str]:
"""Рекурсивно ищет файлы с именем numbers.txt."""
found: list[str] = []
for root, dirs, files in os.walk(directory):
if "numbers.txt" in files:
found.append(os.path.join(root, "numbers.txt"))
return found
4
Посчитайте сумму чисел в одном файле
from typing import Optional
def sum_numbers_in_file(path: str) -> Optional[float]:
"""Суммирует числа в файле. Возвращает None при ошибке."""
total = 0.0
try:
with open(path, "r", encoding="utf-8") as file:
for line_number, line in enumerate(file, start=1):
line = line.strip()
if not line:
continue
try:
total += float(line)
except ValueError:
logging.error(f"Некорректное число в {path}:{line_number} — '{line}'")
except FileNotFoundError:
logging.error(f"Файл не найден: {path}")
return None
except UnicodeDecodeError as e:
logging.error(f"Ошибка кодировки в {path}: {e}")
return None
return total
⚠️ Проверить по документации: менеджер контекста
with для открытия файлов не разбирается в исходной лекции, но является рекомендуемым способом автоматического закрытия файла.
5
Запишите результаты в summary.txt
def main() -> None:
if len(sys.argv) != 2:
print("Использование: python process_numbers.py <директория>")
sys.exit(1)
source_dir = sys.argv[1]
if not os.path.isdir(source_dir):
print(f"Ошибка: директория '{source_dir}' не существует.")
sys.exit(1)
files = find_numbers_files(source_dir)
if not files:
print("Файлы numbers.txt не найдены.")
return
with open("summary.txt", "w", encoding="utf-8") as output:
for path in files:
total = sum_numbers_in_file(path)
if total is not None:
output.write(f"{path}: {total}\n")
print(f"{path}: {total}")
else:
output.write(f"{path}: ошибка обработки\n")
if __name__ == "__main__":
main()
✅ Полное решение
# process_numbers.py
import logging
import os
import sys
from typing import Optional
logging.basicConfig(
filename="processing.log",
format="%(asctime)s - %(levelname)s - %(message)s",
level=logging.ERROR,
)
def find_numbers_files(directory: str) -> list[str]:
"""Рекурсивно ищет файлы с именем numbers.txt."""
found: list[str] = []
for root, dirs, files in os.walk(directory):
if "numbers.txt" in files:
found.append(os.path.join(root, "numbers.txt"))
return found
def sum_numbers_in_file(path: str) -> Optional[float]:
"""Суммирует числа в файле. Возвращает None при ошибке."""
total = 0.0
try:
with open(path, "r", encoding="utf-8") as file:
for line_number, line in enumerate(file, start=1):
line = line.strip()
if not line:
continue
try:
total += float(line)
except ValueError:
logging.error(
f"Некорректное число в {path}:{line_number} — '{line}'"
)
except FileNotFoundError:
logging.error(f"Файл не найден: {path}")
return None
except UnicodeDecodeError as e:
logging.error(f"Ошибка кодировки в {path}: {e}")
return None
return total
def main() -> None:
if len(sys.argv) != 2:
print("Использование: python process_numbers.py <директория>")
sys.exit(1)
source_dir = sys.argv[1]
if not os.path.isdir(source_dir):
print(f"Ошибка: директория '{source_dir}' не существует.")
sys.exit(1)
files = find_numbers_files(source_dir)
if not files:
print("Файлы numbers.txt не найдены.")
return
with open("summary.txt", "w", encoding="utf-8") as output:
for path in files:
total = sum_numbers_in_file(path)
if total is not None:
output.write(f"{path}: {total}\n")
print(f"{path}: {total}")
else:
output.write(f"{path}: ошибка обработки\n")
if __name__ == "__main__":
main()
🧪 Как проверить решение
- Создайте тестовую директорию с вложенными папками.
- В нескольких папках создайте файлы
numbers.txtс числами и несколькими некорректными строками. - Запустите:
python process_numbers.py путь_к_тестовой_директории. - Убедитесь, что в
summary.txtпоявились результаты для каждого файла. - Проверьте
processing.log: некорректные строки должны быть записаны как ERROR. - Попробуйте запустить без аргументов и с несуществующей директорией — программа должна вывести понятное сообщение.
💡 Советы и типичные ошибки
- Не ловите «голый»
except:— указывайте конкретные исключения. - Используйте
os.path.joinвместо ручной склейки путей. - Проверяйте аргументы
sys.argvперед обращением по индексу. - Не коммитьте лог-файлы и
summary.txt— добавьте их в.gitignore.