Практические применения: работа с файлами и папками в ОС
С помощью короткой программы на питоне можно решить довольно широкий спектр задач которые до появления компьютеров просто не существовали.
Это работа с файлами и папками операционной системы, работа с изображениями, mp3, pdf, электронной почтой, получение информации из сети интернет и много другое.
В интернете можно найти много статей, которые помогут начинающему программисту разобраться с возникшей проблемой и решить задачу. Но даже в готовой статье надо уметь найти необходимую информацию.
Итак, вашему вниманию предлагается несколько статей, материал из которых позволяет решить задачи этого контеста.
В каждой задаче нужно написать программу, которая решает поставленную проблему.
В тестовую систему необходимо сдать текст программы, а после многострочный комментарий """...""", в котором ответ на задачу.
Например, если задача — «Вычислить 2 в сотой степени», то возможный правильный ответ такой:
В архиве вы найдёте структуру папок с таксономией приматов (виды, семейства и т.д.).
Где-то в глубине там даже есть человек разумный :).
Необходимо вывести список из всех файлов, которые есть в папке Primates или её подпапках.
Порядок файлов не важен.
Папку Primates из архива нужно положить куда-нибудь и скопировать путь к ней.
Если путь имеет вид C:\Some\Directory\Users\Foo\Primates,
то в начале программы рекомендуется сделать
os.chdir(r'C:\Some\Directory\Users\Foo')
После этого папка Primates окажется прямо в текущей рабочей папке программы.
Если бы стартовой была папка Primates\Haplorrhini\Simiiformes\Catarrhini\Hominoidea\Hominidae, то ответ был бы такой:
В условиях задачи A выведите список имён всех подпапок в папке Primates или её подпапках.
Если бы стартовой была папка Primates\Haplorrhini\Simiiformes\Catarrhini\Hominoidea\Hominidae, то ответ был бы такой:
import os
from pathlib import Path
...
"""
Homininae
Ponginae
Gorilla
Homo
Pan
Gorilla_beringei
Gorilla_gorilla
Pongo
Pongo_pygmaeus
"""
E: Список папок с полными путями
В условиях задачи 04 выведите полные пути к папкам от Primates.
Если бы стартовой была папка Primates\Haplorrhini\Simiiformes\Catarrhini\Hominoidea\Hominidae, то ответ был бы такой:
import os
from pathlib import Path
...
"""
Hominidae\Homininae
Hominidae\Ponginae
Hominidae\Homininae\Gorilla
Hominidae\Homininae\Homo
Hominidae\Homininae\Pan
Hominidae\Homininae\Gorilla\Gorilla_beringei
Hominidae\Homininae\Gorilla\Gorilla_gorilla
Hominidae\Ponginae\Pongo
Hominidae\Ponginae\Pongo\Pongo_pygmaeus
"""
Практическое задание: восстановление фотографий
В новой серии задач мы отрабатываем следующий сценарий:
из-за резкого скачка электричества ваш компьютер вырубился во время записи файла на диск.
В результате повреждена файловая система, поэтому уже невозможно найти свои файлы в "обычных" местах.
На диске остались фотографии, которые вам дороги.
С помощью специальной программы, которая сканирует весь диск и ищет последовательности байтов, похожие на фотографии,
вы добыли всё, что можно.
Так как файловая система умерла, то имён файлов и прочих атрибутов нет, есть только гора файлов с бессмысленными именами.
Так как вы много работали с фотографиями, то там много повторов фотографий.
А вот и архив с этими фотографиями.
Для его открытия используйте 7z (брать отсюда).
План по наведению порядка:
Получить список файлов;
Посчитать md5-хэш каждого файла. У одинаковых фотографий будет одинаковый хеш, а у разных — разный;
Отобрать по одному файлу для каждого хеша, а остальные — удалить;
В каждом файле в EXIF найти информацию о дате и времени съёмки;
Переименовать каждый файл в соответствии с датой и временем съёмки.
Для того, чтобы каждый раз не клеить полный путь к имени файла, удобно перейти прямо в директорию к фотографиям при помощи
os.chdir('C:\\some\\path\\resc_photos')
Итак, поехали!
F: md5-хеши файлов
Для каждого файла из архива посчитайте его md5-хеш.
Выведите все пары (ИМЯ_ФАЙЛА, ХЕШ).
Порядок файлов неважен.
Если бы в папке были бы только файлы 0spuuzog.jpg, 1e1ztfom.jpg и 82t56870.jpg, то правильный ответ был бы таким:
import os
import hashlib
from pathlib import Path
...
"""
0spuuzog.jpg 2b04cbfba96acc2b20fb41a65c00116d
1e1ztfom.jpg a46e61e2cf9725d569ad755dbdd189c0
82t56870.jpg 2b04cbfba96acc2b20fb41a65c00116d
"""
G: Отбор уникальных файлов
Отберите все уникальные фотографии и выведите их имена.
Если бы в папке были бы только файлы 0spuuzog.jpg, 1e1ztfom.jpg и 82t56870.jpg, то правильный ответ был бы таким:
import os
import hashlib
from pathlib import Path
...
"""
0spuuzog.jpg
1e1ztfom.jpg
"""
H: Удаление лишнего
Получите список всех файлов, которые не лежат в списке из задачи G.
Удалите все эти повторяющиеся файлы.
В тестовую систему необходимо сдать код программы, которая делает это, а также выводит список удаляемых файлов.
Если бы в папке были бы только файлы 0spuuzog.jpg, 1e1ztfom.jpg и 82t56870.jpg, то правильный ответ был бы таким:
import os
import hashlib
from pathlib import Path
...
"""
82t56870.jpg
"""
I: Дата съёмки
Известно, что фотографии сняты в августе 2015 года.
В начале каждой фотографии находится EXIF — метаданные, например, дата-время съёмки, модель камеры и т.д.
Теоретически их можно расшифровать, но сейчас в этом нет необходимости. Нужную дату можно найти и так.
Откройте файл при помощи notepad++, и вы её увидите.
После этого будет не сложно добыть дату для каждой фотографии автоматически.
Здесь следует учитывать, что данные в файле не текстовые, а бинарные, поэтому открывать файл стоит так:
open(filename, 'rb')
Здесь r отвечает за чтение, а b — за то, что чтение бинарных данных.
Бинарные строки очень похожи на обычные, только в коде перед ними стоит буква r.
С ними можно делать почти все операции, что и с обычными текстовыми.
Те символы бинарной строки, код которых не лежит в диапазоне acsii (от 32 до 127), выводятся как их код в 16-ричной системе счисления.
Для получения из обычной текстовой строки бинарной используется метод encode:
Выведите для каждого из оставшихся файлов дату и время съёмки в том виде, в котором они добываются из файла.
Если бы в папке были бы только файлы 0spuuzog.jpg, 1e1ztfom.jpg и 82t56870.jpg, то правильный ответ был бы таким:
import os
from pathlib import Path
...
"""
0spuuzog.jpg b'2015:08:23 14:26:12'
1e1ztfom.jpg b'2015:08:19 16:05:07'
"""
J: Переименование
Теперь ничего не стоит переименовать файлы в имена вида "yyyy-mm-dd_hh-mm-ss.jpg".
Ну, почти ничего, кроме того, что некоторые фотографии сняты в одну и ту же секунду.
Если вдруг так окажется, то добавьте в конец имени файла перед ".jpg" один, два или три символа "_"
(например, "2015-08-23_14-26-12_.jpg").
В тестовую систему необходимо сдать код программы, которая делает это, а также выводит имена новых файлов.
Если бы в папке были бы только файлы 0spuuzog.jpg, 1e1ztfom.jpg и 82t56870.jpg, то правильный ответ был бы таким:
import os
from pathlib import Path
...
"""
2015-08-23_14-26-12.jpg
2015-08-19_16-05-07.jpg
"""
K: Чтение EXIF
Решение в предыдущих двух задачах не сработает, если у нас будет архив фотографий за 10 лет.
Мы не сможем уверенно искать дату съёмки по строке "2015.08", ведь это может оказаться датой изменения, а не съёмки.
Поэтому более правильное решение — расшифровать EXIF.
Стандарт открыт, поэтому можно написать свою программу по его расшифровке.
Однако это достаточно трудоёмко.
Один из плюсов питона в том, что большинство подобных задач уже решены, и всё, что требуется, это найти подходящий пакет.
В данном случае один из подходящих нам пакетов — это exif.
Установка пакета exif
Установка пакетов для Python в операционной системе Windows, увы, зачастую вызывает затруднения.
Чтобы его установить, нужно выполнить в командной строке pip install exif (win+R, затем cmd).
Если у вас старая версия Python, не установлен pip, или при установке вы не поставили галочку "Добавить Python в PATH",
то это не сработает.
Тогда попробуйте запустить такую программу:
import os, sys
python = sys.executable
user = '--user' if 'venv' not in python else ''
cmd = '"{}" -m pip install exif --upgrade {}'.format(python, user)
print(cmd)
os.system(cmd)
Напишите программу, которая получает дату и время съёмки из EXIF для каждой фотографии при помощи модуля exif.
В тестовую систему необходимо сдать код программы, которая делает это, а также выводит полученные временные отметки.
Если бы в папке были бы только файлы 0spuuzog.jpg, 1e1ztfom.jpg и 82t56870.jpg, то правильный ответ был бы таким:
import os
import exif
from pathlib import Path
...
"""
2015:08:23 14:26:12
2015:08:19 16:05:07
"""
L: Выбор объектива
При выборе объектива для фотоаппарата возникает вопрос: какие диапазон фокусных расстояний (углов поля зрения, см. картинку в википедии) вам необходим.
Что выбирать, длиннофокусный объектив, широкоугольный объектив и т.д.?
Довольно надёжный способ — посмотреть, какими фокусными расстояними вы пользуетесь.
Напишите программу, которая получает фокусное расстояние кадра из EXIF для каждой фотографии при помощи модуля exif.
Для каждого используемого фокусного расстояния выведите количество кадров (нужно отсортировать по увеличению фокусного расстояния).
Учтите, что вам нужно эквивалентное фокусное расстояние,
так как именно оно участвует в маркировке объективов.
В тестовую систему необходимо сдать код программы, которая делает это, а также выводит количества кадров.
Если бы в папке были бы только файлы 0spuuzog.jpg, 1e1ztfom.jpg и 82t56870.jpg, то правильный ответ был бы таким:
import os
import exifread
from pathlib import Path
...
"""
24: 1
70: 1
"""
M: Разложить по полочкам
После того, как мы «восстановили» имена файлов с фотографиями,
появилась необходимость разложить их в отдельные папки в соответствии с поездками.
Будем тренироваться на «кошках».
Внутри архива вы найдёте несколько файлов вида 2013-02-04_04-46-01.txt.
Нужно разложить их по папкам вида yyyy/mm/dd, где yyyy, mm и dd — соответствующие части даты, а также переименовать:
убрать из имени файла дату.
В тестовую систему необходимо сдать zip-архив, в котором находится папка crt_dirs с нужно структурой,
а также py-файл с программой. Если бы архив из условия состоял лишь из файлов 2013-01-16_00-24-33.txt, 2013-01-16_16-40-26.txt и 2015-11-25_16-51-47.txt,
то в правильная структура в zip файле ответа выглядела бы так: