Python добавить файл в архив
Стандартная библиотека Python предоставляет отличные модули и инструменты практически для любой задачи, о которой можно только подумать. Модули для работы со сжатыми файлами (архивами) не являются исключением. Будь то основные контейнеры, такие как tar и zip , или специальные инструменты или форматы, такие как gzip и bz2 , или даже более экзотические форматы, такие как lzma , в Python есть все. Итак, чтобы ориентироваться во всех доступных вариантах, в этом материале рассмотрим модули, позволяющие работать с архивами, а так же узнаем, как сжимать, распаковывать, проверять, тестировать и защищать архивы всех видов форматов с помощью стандартной библиотеки Python.
Атрибуты данных
ZipFile.filename :
Атрибут ZipFile.filename возвращает имя файла ZIP.
ZipFile.debug :
Атрибут ZipFile.debug устанавливает уровень вывода отладочной информации. Уровень может быть установлен от 0 (по умолчанию, без выходных данных) до 3-х (максимальный выходной). Отладочная информация записывается в sys.stdout .
При назначении комментария экземпляру класса zipfile.ZipFile , созданному в режиме 'w' , 'x' или 'a' , он должен быть не длиннее 65535 байт. Комментарии длиннее этого будут усечены.
Модуль zipfile в Python помогает нам в работе с zip файлами. Сегодня мы узнаем, как читать детали zip-архива, создавать и распаковывать с помощью модуля zipfile.
Модуль zipfile важен даже для промышленного приложения. Это связано с тем, что на серверах файлы, загружаемые через веб-приложения, часто архивируются, а затем сохраняются для экономии места на сервере. Начнем с примеров модуля zipfile. Этот модуль также похож на модуль tarfile.
Обратите внимание, что в демонстрационных целях у нас есть ZIP-файл с именем Archive.zip с некоторыми текстовыми файлами, и этот ZIP-файл находится в каталоге, в котором мы запускаем программы.
Копирование
Скопировать файл можно с помощью функции shutil.copy(source, destination) . Правила расположения копии будут те же, что и при использовании shutil.move , за тем исключением, что если destination существует и не является файлом, то он будет заменён и ошибки это не вызовет.
Скопировать папку для операционной системы сложнее, ведь мы всегда хотим скопировать не только папку, но и её содержимое. Для копирования папок используйте shutil.copytree(source, destination) . Обратите внимание, что для этой функции destination всегда должно быть путём конечного расположения файлов и не может быть уже существующей папкой.
Добавление файла с другим именем
В архив можно добавлять файлы участников с другим именем. Вот пример программы, показывающей, как это можно сделать:
Посмотрим на результат этой программы:
Низкоуровневый модуль bz2 .
Следующий модуль bz2 , также предоставляет одноименный формат сжатия bz2 . Модуль используется очень похоже на описанный выше модуль zlib :
Интерфейс этих двух модулей в значительной степени идентичен, поэтому, в приведенном выше примере этап сжатия был сокращен практически до одной строки, а так же использовался os.stat для проверки размера файлов.
Создаем структуру проекта
Для начала создадим директорию для пакета. Ее минимальный набор файлов состоит из: файла дистрибьюции ( setup.py ) описывающего метаданные и python кода проекта (в нашем случае модуля helloworld).
Также, xорошим тоном считается создание в корне директории файла с описанием проекта: README.txt .
Получаем следующую структуру:
Наша корневая директория helloworld-project будет содержать мета-данные пакета и вспомогательные файлы (тесты, лицензию, документацию и т.д.), а поддиректория helloworld непосредственно сам модуль helloworld .
Теперь отредактируем файл: helloworld/core.py и добавим логику нашего приложения (получение и вывод строки "Hello World!"):
Удаление
Удалить файл можно с помощью функции os.remove , а пустую папку с помощью функции os.rmdir .
А вот для удаления папки с содержимым вновь понадобится shutil . Для удаления такой папки используйте shutil.rmtree .
Будьте осторожны, команды удаления стирают файл, а не перемещают его в корзину, вне зависимости от операционной системы! После такого удаления восстановить файл может быть сложно или вовсе невозможно.
- В текущей папке лежат файлы с расширениями .mp3 , .flac и .oga . Создайте папки mp3 , flac , oga и положите туда все файлы с соответствующими расширениями.
- В текущей папке лежит две других папки: vasya и mila , причём в этих папках могут лежать файлы с одинаковыми именами, например vasya/kursovaya.doc и mila/kursovaya.doc . Скопируйте все файлы из этих папок в текущую папку назвав их следующим образом: vasya_kursovaya.doc , mila_test.pdf и т.п.
- В текущей папке лежат файлы следующего вида: S01E01.mkv , S01E02.mkv , S02E01.mkv и т.п., то есть все файлы начинаются с S01 или S02 . Создайте папки S01 и S02 и переложите туда соответствующие файлы.
- В текущей папке лежат файлы вида 2019-03-08.jpg , 2019-04-01.jpg и т.п. Отсортируйте файлы по имени и переименуйте их в 1.jpg , 2.jpg , …, 10.jpg , и т.д.
- В текущей папке лежат две другие папки: video и sub . Создайте новую папку watch_me и переложите туда содержимое указанных папок (сами папки класть не надо).
- В текущей папке лежат файлы типа Nina_Stoletova.jpg , Misha_Perelman.jpg и т.п. Переименуйте их переставив имя и фамилию местами.
- В текущей папке лежит файл list.tsv , в котором с новой строки написаны имена некоторых других файлов этой папки. Создайте папку list и переложите в неё данные файлы.
Для тестирования вашей программы положите в репозиторий файлы и папки с соответствующими именами. Файлы должны быть пустыми, если не указано обратного.
Одна из действительно полезных вещей в python — это система скриптов установки. Любой, серьезно увлекающийся python-программированием разработчик рано или поздно сталкивается с ней. Но из-за гибкости инструментария скриптов установки, их документация весьма раздута. На текущий момент имеется набор утилит (setuptools, distutils, distribute) выполняющих одинаковые задачи.
В данной статье я на конкретных примерах покажу как создать и настроить простой python-пакет.
Наш проект будет иметь следующую функциональность:
- Метод возвращающий строку: "Hello World!";
- Команда helloworld печатающая эту строку в стандартный вывод.
Низкоуровневый модуль lzma .
Последним из этих низкоуровневых модулей является lzma , и чтобы не показывать один и тот же код снова, выполним сжатие фрагментами, по 1024 байта. Такой способ может пригодится, если файл очень большой и целиком не помещается в оперативную память.
Начинаем с создания исходного файла, состоящего из слов, извлеченных из словаря, расположенного в /usr/share/dict/words . Это делается для того, чтобы потом можно было фактически подтвердить, что распакованные данные идентичны оригиналу.
Для проверки, открываем и распаковываем файл обычным способом и выводим первые 5 слов.
Использование модуль gzip совместно с shutil .
Переходим к модулям более высокого уровня и теперь будем использовать модуль gzip для тех же задач. Пример того, как применение модуля shutil может облегчить архивирования больших файлов.
В этом примере были объединены использование модулей gzip , и shutils . Может показаться, что здесь делается такое же сжатие, что и в примерах модулей zlib или bz2 , но благодаря функции модуля shutil.copyfileobj , получаем пошаговое инкрементное сжатие без необходимости перебирать данные в цикле, как это делалось с lzma .
Одним из преимуществ модуля gzip является то, что он предоставляет интерфейс командной строки, и это не gzip и gunzip в Linux, а интеграция с Python:
Высокоуровневый модуль zipfile .
Помимо основных операций сжатия/распаковки, модуль zipfile включают некоторые другие служебные методы, такие как проверка контрольных сумм, использование паролей или просмотр файлов в архивах.
Это довольно длинный фрагмент кода, но он охватывает все важные функции модуля zipfile . Код начинается с создания ZIP-архива при помощи контекстного менеджера ZipFile в режиме записи - 'w' , а затем, в него добавляются файлы. Можно заметить, что при добавлении файлов в архив, последние не открываются на чтение, а просто передается имя файла в метод ZipFile.write() .
После добавления файлов, устанавливаем пароль архива, используя метод ZipFile.setpassword .
Далее, для подтверждения того что сжатие работает, открываем архив. Перед чтением любых файлов, проверяем CRC и заголовки файлов, после чего извлекаем информацию обо всех файлах, присутствующих в архиве. В этом примере просто выведем список объектов zipfile.ZipInfo . Используя атрибуты этого объекта, можно получить CRC, размер, тип сжатия и т. д.
После проверки файлов, откроем и прочитаем один из них. Очевидно, что он имеет ожидаемое содержимое, поэтому продолжим извлекать его в файл, указанный по пути /tmp/ .
Помимо создания архивов, модуль zipfile позволяет также добавлять файлы в существующие архивы. Для этого нужно изменить режим открытия архива на "добавить" - 'а' :
Как и в случае с модулем gzip , модуль zipfile в Python имеет интерфейс командной строки. Для выполнения базового архивирования и извлечения используйте следующее:
Содержание:
ZipFile.close() :
Метод ZipFile.close() закрывает файл архива. Необходимо вызвать этот метод перед выходом из программы, иначе не вся информация будет записана или используйте менеджер контекста.
ZipFile.getinfo(name) :
Метод ZipFile.getinfo() возвращает объект zipfile.ZipInfo() с информацией для элемента архива с именем name .
Вызов метода ZipFile.getinfo() для несуществующего имени элемента архива вызовет исключение KeyError .
ZipFile.infolist() :
Метод ZipFile.infolist() возвращает список, содержащий объект zipfile.ZipInfo() для каждого члена архива.
Объекты находятся в том же порядке, что и в реальном ZIP-файле на диске.
ZipFile.namelist() :
Метод ZipFile.namelist() возвращает список членов архива по имени.
ZipFile.open(name, mode='r', pwd=None, *, force_zip64=False) :
Метод ZipFile.open() предоставляет доступ к элементу архива в виде двоичного файлового объекта.
- Аргумент name может быть либо именем файла в архиве, либо объектом zipfile.ZipInfo() .
- Аргумент mode , если он включен, должен иметь значение 'r' (по умолчанию) или 'w' .
- Аргумент pwd - это пароль, используемый для расшифровки зашифрованных ZIP-файлов.
Метод ZipFile.open() является менеджером контекста и поэтому поддерживает оператор with :
В режиме mode='r' файлоподобный объект ZipExtFile доступен только для чтения и предоставляет следующие методы: read() , readline() , readlines() , seek() , tell() , __iter__() , __next__() . Эти объекты могут работать независимо от объекта ZipFile`.
В режиме mode='w' возвращается дескриптор доступного для записи файла, который поддерживает метод write() . Когда дескриптор доступного для записи файла открыт, попытка чтения или записи других файлов в ZIP-архиве вызовет ошибку ValueError .
При записи файла, если размер файла заранее неизвестен, но может превышать 2 ГБ, то передайте force_zip64=True для поддержки больших файлов. Если размер файла известен заранее, то создавайте объект zipfile.ZipInfo() с установленным аргументом file_size и используйте его в качестве параметра имени.
Примечание.
Методы ZipFile.open() , ZipFile.read() и ZipFile.extract() могут принимать в качестве имени файла объект zipfile.ZipInfo() . Вы оцените это при попытке прочитать ZIP-файл, содержащий элементы архива с повторяющимися именами.
ZipFile.extract(member, path=None, pwd=None) :
Метод ZipFile.extract() извлекает элемент архива member в текущий рабочий каталог.
- Аргумент member должен быть полным именем или объектом zipfile.ZipInfo() . Информация о его файле извлекается максимально точно.
- Аргумент пути path указывает другой каталог для извлечения.
- Аргумент pwd - пароль, используемый для зашифрованных файлов.
Метод ZipFile.extract() возвращает созданный нормализованный путь (каталог или новый файл).
Примечание.
Если имя файла архива является абсолютным путем, разделяющая точка диска drive/UNC и начальная (обратная) косая черта будут удалены, например: ////foo/bar становится foo/bar в Unix, а C:\foo\bar становится foo\bar в Windows. И все компоненты '..' в имени файла элемента архива будут удалены, например: ../../foo../../ba..r становится foo../ba..r . В Windows недопустимые символы : , < , >, | , " , ? и * заменяются подчеркиванием _ .
ZipFile.extractall(path=None, members=None, pwd=None) :
Метод ZipFile.extractall() извлекает все элементы архива в текущий рабочий каталог.
- Аргумент пути path указывает другой каталог для извлечения.
- Аргумент members не обязателен и должен быть подмножеством списка, возвращаемого методом ZipFile.namelist() .
- Аргумент pwd - пароль, используемый для зашифрованных файлов.
ZipFile.printdir() :
Метод ZipFile.printdir() печатает оглавление архива в sys.stdout .
ZipFile.setpassword(pwd) :
Метод ZipFile.setpassword() устанавливает pwd в качестве пароля по умолчанию для извлечения зашифрованных файлов.
ZipFile.read(name, pwd=None) :
Метод ZipFile.read() возвращает байты прочитанный из файла в архиве с именем name .
- Аргумент name - строка с полным именем файла в архиве или объект zipfile.ZipInfo() . Архив должен быть открыт для чтения или добавления.
- Аргумент pwd - это пароль, используемый для зашифрованных файлов и если он указан, он переопределит пароль по умолчанию, установленный с помощью метода ZipFile.setpassword() .
Вызов ZipFile.read() для экземпляра класса zipfile.ZipFile , который использует метод сжатия, отличный от ZIP_STORED , ZIP_DEFLATED , ZIP_BZIP2 или ZIP_LZMA , вызовет исключение NotImplementedError . Также будет возникать ошибка, если соответствующий модуль сжатия недоступен.
ZipFile.testzip() :
Метод ZipFile.testzip() читает все файлы в архиве и проверяет их CRC и заголовки файлов. Возвращает имя первого неверного/битого файла или если все "путем", то возвращает None .
ZipFile.write(filename, arcname=None, compress_type=None, compresslevel=None) :
Метод ZipFile.write() добавляет файл с именем filename в архив, присвоив ему имя в архиве arcname , по умолчанию это будет то же самое, что и filename , но без буквы диска и с удаленными начальными разделителями пути.
Если задан аргумент compress_type , то он переопределяет значение этого параметра, заданное при создании экземпляра класса zipfile.ZipFile для добавления в архив нового элемента. Аналогично, если задан аргумент compresslevel , то он переопределит конструктор. Архив должен быть открыт в режиме 'w' , 'x' или 'a' .
Примечания:
- Имена архивов должны относиться к корню архива, то есть они не должны начинаться с разделителя пути.
- Если arcname или имя файла, если arcname не указано содержит нулевой байт, имя файла в архиве будет обрезано до нулевого байта.`
ZipFile.writestr(zinfo_or_arcname, data, compress_type=None, compresslevel=None) :
Метод ZipFile.writestr() записывает файл в архив.
Аргумент data это данные (содержимое) файла, которые могут быть str или bytes . Если данные представляют из себя строки str , то они сначала кодируется как UTF-8.
Аргумент zinfo_or_arcname - это либо имя файла, которое будет дано в архиве, либо объект ZipInfo . Если это объект ZipInfo , то необходимо указать аргумент data . Если это имя файла, то дата и время устанавливаются на текущую дату и время. Архив должен быть открыт в режиме 'w' , 'x' или 'a' .
Если задан аргумент compress_type , то он переопределяет значение этого параметра, заданное при создании экземпляра класса zipfile.ZipFile для добавления в архив нового элемента. Аналогично, если задан аргумент compresslevel , то он переопределит конструктор.
Примечание.
При передаче экземпляра zipfile.ZipInfo() в качестве параметра zinfo_or_arcname используется метод сжатия, указанный в элементе compress_type данного экземпляра. По умолчанию конструктор zipfile.ZipInfo() устанавливает для этого члена значение zipfile.ZIP_STORED .
Управление файлами проекта (MANIFEST.in)
На текущий момент при сборке нашего пакета distutils включает в него только python-файлы. Необходимо включить в него файл helloworld/templates/index.html без которого проект работать не будет.
Чтобы сделать это мы должны сообщить distutils какие еще файлы надо включать в наш проект. Один из способов — это создание файла MANIFEST.in :
Данная команда указывает distutils на включение в проект всех html файлов в директории helloworld/templates .
Также придется обновить setup.py :
Теперь шаблоны будут включены в наш проект.
Создание и запуск тестов
Хорошей практикой считается создание тестов для вашего проекта. Добавим простейшую реализацию, файл tests.py :
И обновим setup.py :
Теперь мы можем произвести предварительное тестирование нашего проекта:
Обратите внимание, что для запуска тестов даже не нужно создание виртуального окружения. Необходимые зависимости будут скачаны в директорию проекта в виде egg пакетов.
Прежде чем вы сможете опубликовать свой проект вам необходимо зарегистрироваться на PyPi. Запишите ваши реквизиты в файле ~/.pypirc :
Все ваш проект готов к публикации. Достаточно ввести соответствующую команду:
Вы не сможете опубликовать пакет helloworld , тк данное имя проекта уже занято.
В данном разделе рассмотрены методы объекта ZipFile с их подробным описанием и примерами. Объект ZipFile получается в результате создания экземпляра класса 'zipfile.ZipFile()'.
Низкоуровневый модуль zlib .
Модуль zlib довольно низкоуровневая библиотека, и следовательно она может использоваться не так часто, поэтому рассмотрим базовое сжатие/распаковку всего файла сразу:
В приведенном выше коде, используется входной файл, который был сгенерирован с данными head -c 1MB /dev/zero > data , что выдает 1 МБ нулей. Далее открываем и считываем этот файл в память, а затем используем функцию сжатия для создания сжатых данных. После эти данные записываются в выходной файл. Чтобы продемонстрировать восстановление данных, снова открываем сжатый файл и используем для него функцию распаковки. При выводе на печать видим, что размеры как сжатых, так и распакованных данных совпадают.
Проверка правильности
Мы также можем проверить, является ли указанный файл действительным ZIP-архивом. Вот пример программы:
Давайте посмотрим на результат этой программы:
Это важный тест, который необходимо выполнить при работе с ZIP-архивами.
Модули Python, позволяющие работать с архивами.
-
предоставляет собой код для работы с форматом сжатия и распаковки методом deflate , который используется такими форматами архивов, как zip , gzip и многими другими. Этот модуль, по сути, использует алгоритм сжатия, совместимый с gzip , только без удобной оболочки. обеспечивает поддержку сжатия bzip2 . Этот алгоритм, как правило, более эффективен, чем метод deflate , но может быть медленнее. Он работает только с отдельными файлами и поэтому не может создавать архивы директорий. представляет собой также название алгоритма. Он может обеспечить более высокую степень сжатия, чем некоторые старые методы, и является алгоритмом, лежащим в основе утилиты xz (точнее, LZMA2 ). использует уже упомянутый алгоритм сжатия zlib и служит интерфейсом, аналогичным утилитам gzip и gunzip . предоставляет служебные методы для работы с архивами и может быть удобным способом создания архивов tar , gztar , zip , bztar или xztar . позволяет работать с zip-архивами в Python. Этот модуль предоставляет все ожидаемые методы для создания, чтения, записи или добавления в ZIP-файлы, а также классы и объекты для упрощения работы с такими файлами. используется для работы с tar-архивами. Он может читать и записывать файлы или архивы gzip , bz2 и lzma . Он также поддерживает другие функции, которые знакомы из утилиты tar .
Создание ZIP-файла
Далее мы начнем с того, что посмотрим, как можно создать ZIP-файл. Чтобы создать новый архив, мы создадим экземпляр ZipFile с режимом w. Обратите внимание: если файл с таким же именем существует, он будет полностью усечен. Итак, убедитесь, что имя вашего файла уникально.
Давайте посмотрим на фрагмент кода для создания zip-файла с помощью модуля zipfile:
Посмотрим на результат этой программы:
Работа с версиями
Номер версии важная часть любого проекта. От него зависит обновление пакетов и разрешение зависимостей. В примере выше мы указали номер версии 1.0 в файле setup.py . Более правильное решение перенести его в файл helloworld/__init__.py чтобы сделать доступным в python-коде. По существующим соглашения для хранения номера версии в модуле, используется переменная __version__.
Изменим файл setup.py , чтобы нам не приходилось редактировать номер версии в двух местах:
Существует множество систем наименования версий в python обычно рекомендуется использовать PEP386. Можно представить, что обозначение версии состоит из номера мажорного, минорного релизов (номера багфикса при необходимости), разделенных точками. В последней части версии разрешается использовать буквы латинского алфавита. Примеры из официальной документации:
Извлечение расширения
Кроме того, может пригодиться функция os.path.splitext , котоая отрезает расширение файла:
Чтение ZIP-файла
Мы начнем с перечисления файлов, находящихся в ZIP-архиве. Вот пример программы:
Посмотрим на результат этой программы:
Мы смогли перечислить файлы, присутствующие в архиве, а также некоторые метаданные для файлов. Обратите внимание, что процесс выполняется очень быстро, так как нам не нужно было распаковывать файл, прежде чем мы могли его прочитать.
Распаковка ZIP-архива
Посмотрим на фрагмент кода:
Давайте посмотрим на результат этой программы:
Обратите внимание, что новый каталог не создается, а файлы помещаются в тот же каталог. Укажите каталог, если вы хотите разместить файлы в определенном месте.
Перемещение и переименование
Для удобной манипуляции с файлами и папками в стандартной библиотеки Python существует специальный модуль shutil . Функция shutil.move(source, destination) позволяет вам переместить любой файл или папку (даже непустую). Обратите внимание, что если destination — это уже существующая папка, то файл/папка будет перемещена внутрь неё, в остальных случаях файл/папка будут скопированы точно по нужному адресу. В случае успеха, функция вернёт новое местоположение файла. Если destination существует и не является папкой, то будет выброшена ошибка.
Как же переименовать файл? Несмотря на то, что os содержит специальную функцию для переименования, нужно понимать, что в рамках одной файловой системы перемещение и переименование — это одно и то же. Когда вы переименовываете файл, его содержимое не переписывается на носителе в другое место, просто файловая система теперь обозначает его положение другим путём.
Извлечение имени файла из пути
Функция os.path.split совершает обратное действие — отрезает имя файла или ниже лежащей папки от пути:
Создание файла
Нет ничего проще, чем создать пустой файл, достаточно открыть несуществующий файл с флагом 'x' :
Конечно, можно было бы использовать флаг 'w' , но тогда уже существующий файл был бы стёрт. С флагом 'x' open либо создаст новый файл, либо выбросит ошибку.
Высокоуровневый модуль tarfile .
И последнее, но не менее важное: модуль tarfile . Этот модуль похож на zipfile , но также реализует некоторые дополнительные функции:
Код примера начинается с простого создания архива, но здесь используется режим доступа 'w:gz' , который указывает, что необходимо использовать сжатие GZ. После этого добавляются все файлы в архив. С помощью модуля tarfile можно передавать, например, символические ссылки или целые каталоги, которые будут добавляться рекурсивно.
Далее, чтобы проверить, что все файлы действительно присутствуют в архиве, используется метод TarFile.getmembers() . Чтобы получить представление об отдельных файлах, можно использовать метод TarFile.gettarinfo() , который предоставит все атрибуты файлов Linux.
Модуль tarfile имеет одну интересную функцию, которой нет в других модулях, а именно возможность изменять атрибуты файлов, когда они добавляются в архив. В приведенном выше фрагменте кода меняется разрешение файла, предоставляя аргумент filter , который изменяет TarInfo.mode . Это значение должно быть представлено в виде восьмеричного числа, здесь 0o100600 устанавливает разрешения на 0600 или -rw------- .
Последнее, что нужно сделать с tar-архивом, это открыть его и распаковать. Для этого открываем его в режиме 'r:gz' , извлекаем информационный объект (member) по имени файла, проверяем, действительно ли это файл, и извлекаем его в нужное место:
Модуль стандартной библиотеки os (от «operation system») предоставляет множество полезных функций для произведения системных вызовов. Одна из базовых функций этого модуля — os.listdir .
С точки зрения операционной системы нет разницы между файлом, папкой или другим подобным объектом, типа ссылки. Поэтому os.listdir() возвращает список как файлов, так и папок. Обратите внимание, что порядок элементов возвращаемого списка не регламентируется, если вам нужно их отсортировать не забудьте сделать это:
Модуль os содержит подмодуль os.path , который позволяет работать с путями файлов и папок. Импортировать этот модуль отдельно не нужно, достаточно выполнить import os .
Проверка типа файла
Кроме прочего, модуль os.path содержит функции для проверки существования файла и для определения его типа:
Производите все манипуляции с файлами с осторожностью, придерживайтесь правила «семь раз отмерь — один раз отрежь». Не забывайте программно производить все возможные проверки перед выполнением операций.
Создание папки
Для создания новой папки используйте os.mkdir(name) . Эта функция выбросит ошибку, если по указанному пути уже существует файл или папка. Если вам нужно создать сразу несколько вложенных папок, то смотрите функцию os.makedirs(name, exist_ok=False) .
Присоединение одной части пути к другой
Работа с путями к файлам и папкам как с простыми строками чревата множеством ошибок и может создать проблемы при переносе программы между различными операционными системами. Правильный путь объединить две части пути — это использование os.path.join :
Управление зависимостями
Добавим функциональности нашему проекту. Создадим команду serve которая будет запускать вебсервер отдающий страницу со строкой "Hello world!" генерируемой нашим модулем. Для этого воспользуемся пакетом Flask.
Добавляем файл helloworld/web.py :
И файл helloworld/templates/index.html :
И опишем команду serve в файле setup.py :
Теперь в нашем проекте появилась зависимость от пакета Flask. Без его установки наше приложение не будет правильно работать. За описание зависимостей в файле setup.py отвечает параметр install_requires:
Проверим установку зависимостей обновив наш пакет и работу команды serve:
Создание команд
Для создания команды helloworld изменим файл setup.py :
В параметре entry_points мы задаем словарь с "точками вызова" нашего приложения. Ключ console_scripts задает список создаваемых исполняемых скриптов (в Windows это будут exe-файлы). В данном случае мы указали создание исполняемого скрипта helloworld при вызове которого будет запускаться метод print_message из модуля helloworld.core.
Переустановим модуль в наше окружение и проверим работу созданного скрипта (для этого прийдется активировать наше окружение):
Похоже все работает.
Редактируем мета-информацию (setup.py)
Заполним файл описания README.rst :
Теперь отредактируем файл setup.py :
Убедитесь, что в вашей системе доступны setuptools, в противном случае установите python-пакет distribute
Этих операций достаточно, чтобы собрать пакет дистрибьюции. Выполните команду сборки:
В случае успеха вы получите файл: dist/helloworld-1.0.tar.gz . Это полноценный, архивированный python-пакет и вы можете распространять его среди прочих разработчиков.
Заключение
В этом руководстве Python по zip-файлам мы увидели, как создавать ZIP-архивы и читать их. Используйте этот модуль для создания заархивированных файлов и обработки их по мере необходимости.
Виртуальное окружение
Virtualenv — пакет применяемый для создания изолированного python-окружения. Используем его для тестирования нашего проекта.
Создадим окружение env:
Команда создаст директорию env внутри нашего проекта и установит туда python, pip и distribute. Произведем в него установку нашего проекта.
И протестируем его работоспособность:
Все работает. Осталось добавить поддержку команды helloworld в консоли.
Читайте также: