Русские Блоги
Файл разделен на двоичные файлы и текстовые файлы. Файл PKL — это двоичный файл, который является Python для сохранения файла.
Прочитайте файл PKL:
Интеллектуальная рекомендация
![]()
Структура данных Java-реализация стека
Структура данных Java-реализация стека Структура данных Java (1) Введение в стек Интерфейс ADT стека Приложение экземпляра заметки Структура данных Java (1) Структура данных. Введение в стек Структура.
![]()
Упаковка и удаление программы Winform
Упаковка и выгрузка программ C # могут быть реализованы в среде IDE Visual Studio. Упакуйте плагин Во-первых, вам необходимо загрузить подключаемый модуль Microsoft Visual Studio Installer Project. Пл.
![]()
Как вызвать страницу OAF на форме при разработке EBS OAF и передать параметры странице OAF
1. Добавьте кнопку или другой элемент в форму и добавьте соответствующий триггер, используйте кнопку здесь и соответствующую страницу OAF в приемнике WHEN-BUTTON-PRESSED. Код выглядит следующим.
Введение в технологию сетевых хранилищ (2) (на основе zt)
http://www.educity.cn/tx/429084.html Сравнение интернет-технологий DAS, NAS и SAN хранилищ В соответствии с расположением устройства и методом доступа, дисковое хранилище можно разделить на вст.
![]()
Настройка балансировщика нагрузки Azure для балансировки нагрузки веб-приложений
В предыдущей статье я представил некоторые основные концепции и сценарии использования Azure Load Balancer. Сегодняшняя статья поможет вам настроить балансировщик нагрузки Azure. Локальные эксперимент.
Вам также может понравиться
Пример цветного устройства Vertex -Диффузе освещение («Книга дракона»)
// File: diffuse.txt matrix ViewMatrix; matrix ViewProjMatrix; vector AmbientMtrl; vector DiffuseMtrl vector LightDirection; vector DiffuseLightIntensity = <0.0f, 0.0f, 1.0f, 1.0f>; vector Ambi.
Nodejs Development Sides Neademon
После изменения кода необходимо перезапустить приложение Express и модификации, которые вы можете вступить в силу. Если каждая модификация кода повторяется, это повлияет на эффективность разработки. Э.
![]()
C ++ реализует лучшую страницу алгоритма поверхности OPT страницы, результат — краткий и краткий
OPT результат Реализовать краткий алгоритм OPT, как показано на рисунке выше Краткое объяснение: вручную введите количество страниц и количество физических блоков, автоматически генерируйте информацию.
![]()
Устройство для голосования Verilog на 7 человек
7 человек голосуют, когда количество голосов равно 4 или больше (то есть больше половины), выведите 1, чтобы указать, что прошло, в противном случае выведите 0, чтобы указать неудачу. метод первый: Ме.
![]()
Основное понимание бинарного дерева
Основная концепция бинарного дерева: Двоичное дерево — это структура дерева, имеющая максимум двух субтотов на узел. Обычно поддерево называют «левым поддеревом» и «правым поддеревом.
How to unpack pkl file?
I have a pkl file from MNIST dataset, which consists of handwritten digit images.
I’d like to take a look at each of those digit images, so I need to unpack the pkl file, except I can’t find out how.
Is there a way to unpack/unzip pkl file?
![]()
4 Answers 4
Generally
Your pkl file is, in fact, a serialized pickle file, which means it has been dumped using Python’s pickle module.
To un-pickle the data you can:
For the MNIST data set
Note gzip is only needed if the file is compressed:
Where each set can be further divided (i.e. for the training set):
Those would be the inputs (digits) and outputs (labels) of your sets.
If you want to display the digits:

The other alternative would be to look at the original data:
But that will be harder, as you’ll need to create a program to read the binary data in those files. So I recommend you to use Python, and load the data with pickle . As you’ve seen, it’s very easy. 😉
Файлы и каталоги в Python
Любая программа в конечном итоге представляет собой обычный набор файлов, сгруппированных по какому-либо признаку по каталогам программы. Поэтому в Python предусмотрен внушительный набор инструментов для работы с файлами и каталогами, которые позволяют выполнять над ними такие операции как создание, удаление, переименование, перемещение, чтение, запись, перезапись и многие другие полезные операции. Но что представляют из себя файлы и каталоги?
(от англ. file) – это именованная область данных на носителе информации.
Имена файлов нужны для того, чтобы точно знать, к какой области данных носителя информации осуществляется запрос. При этом большинство операционных систем в целях однозначности не допускает использование двух файлов с полностью идентичными именами в одном каталоге. Что касается набора символов, которые разрешается использовать для имен файлов, а также максимально допустимой длины имен файлов, то они зависят от используемой файловой системы. Например, Windows допускает использование в имени файла заглавных и строчных букв, цифр, некоторых знаков препинания и пробела, но запрещает использование символов > , , / , \ , | , ? , * , : , » . При этом максимально допустимая длина имен файлов в различных системах обычно не превышает 256 символов.
Чтобы помочь системе определить тип файла и, соответственно, приложение для работы с ним, в имени файла обычно указывается его расширение, которое отделяется от остальной части имени точкой. Примерами расширений файлов могут служить: .txt – обычный текстовый файл, .py – файл с кодом Пайтона , .html – файл, представляющий собой html -документ, .jpg – файл изображения в формате jpg и огромное число других расширений.
Когда файлов становится слишком много, возникает необходимость их упорядочивания и группировки. Для этих целей используются каталоги или директории.
или (от англ. directory) – это специальный объект файловой системы, который используется для упрощения организации файлов. В графическом пользовательском интерфейсе каталоги также называют . В любом случае каталог представляет собой файл, содержащий записи о входящих в него файлах или других каталогах.
Каталог, прямо или косвенно включающий в себя все прочие каталоги и файлы программы, называется . А каталог, в котором находится текущий каталог, называется .
Как было сказано выше, большинство операционных систем не разрешает использование двух файлов с полностью идентичными именами в одном каталоге. В то же время вполне допустимо создавать для одного и того же файла несколько имен при помощи жестких ссылок.
или (от англ. hard link) называют различные имена одного и того же файла, которые могут создаваться в пределах одного физического носителя.
После создания жесткой ссылки сказать где настоящий файл, а где хардлинк невозможно, так как они полностью равноправны. Сама же область данных существует до тех пор, пока не будут удалены полностью все имена. Кроме того, при редактировании файла через одну из ссылок на него, содержимое по другим ссылкам также изменяется.
Как следует из определения, создание жестких ссылок одного и того же файла на разных физических носителях (например, жестких дисках) невозможно. Однако данное ограничение можно обойти при помощи символических ссылок.
или (от англ. symbolic link) – это специальный файл в файловой системе, содержащий в себе ссылку на другой файл или директорию, в том числе, и расположенный на другом физическом носителе.
Символическая ссылка занимает ровно столько места в файловой системе, сколько требуется для записи её содержимого, которое представляет собой строку, содержащую путь к определенному файлу или каталогу. Если символьная ссылка указывает на файл, который не существует, ее называют . При попытке обращения к файлу посредством битой ссылки обычно выводится соответствующее предупреждение.
Рассмотрим основные встроенные возможности языка Python для работы с файлами и каталогами.
Функция open: запись и чтение файлов
Редактирование содержимого файла подразумевает осуществление таких операций, как открытие и закрытие файла, чтение и запись, получение текущего значения файлового указателя и его перемещение в соответствии с заданными параметрами, сброс файлового буфера и некоторые другие операции. При этом, используя для редактирования соответствующие функции Python , нужно иметь также и некоторое представление о понятиях, которые имеют непосредственное отношение к работе с файлами. Приведем краткое описание наиболее важных из них.
- (от англ. file descriptor) – неотрицательное целое число, которое операционная система возвращает при открытии файла (в случае, если это возможно) и с помощью которого выполняются все остальные файловые операции. По завершении операций и закрытии файла дескриптор теряет смысл.
- – число, указывающее величину смещения относительно нулевого байта в файле. Обычно по этому адресу осуществляется чтение/запись, если конечно вызов операции чтения/записи не предусматривает указание адреса. При выполнении операций чтения/записи файловый указатель смещается на число прочитанных/записанных байт. В результате последовательный вызов операций чтения позволяет прочитать весь файл не обращая внимания на его размер.
- – специально выделенный участок памяти (буфер), в котором операционная система осуществляет кэширование файловых операций. При закрытии файла буфер сбрасывается.
- – режим устанавливающий разрешения на чтение и запись файла при его открытии.
Для чтения и записи файлов в Python предназначена встроенная функция open(file, mode=’r’, buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None) , которая возвращает специальный итерируемый файловый объект, связанный с целевым файлом. Если файл не может быть открыт, бросается исключение OSError . Обязательным является только первый параметр, в качестве которого необходимо передавать строку с путем к файлу. Все остальные параметры необязательны. Пройдемся по ним.
- file – строка, содержащая абсолютное или относительное значение пути к файлу.
- mode=’r’ – строка с индикатором режима, в котором следует открыть файл:
- ‘r’ – открыть файл на чтение (значение по умолчанию).
- ‘w’ – открыть файл на запись (содержимое файла удаляется, а если его нет, то создается новый).
- ‘x’ – создать файл и открыть его на запись либо сгенерировать исключение FileExistsError , если файл с таким именем уже существует.
- ‘a’ – открыть файл на дозапись (содержимое файла не удаляется, а запись новой информации осуществляется в конец файла).
- ‘b’ – открыть файл в бинарном режиме; используется как дополнительный флаг, например, ‘rb’ , ‘wb’ или ‘ab’ .
- ‘t’ – открыть файл в текстовом режиме; используется как дополнительный флаг по умолчанию.
- ‘+’ – открыть файл на чтение и запись одновременно; используется как дополнительный флаг:
- ‘r+’ – открыть существующий файл на чтение и запись, поместив файловый указатель в начало файла;
- ‘w+’ – открыть существующий файл на запись и чтение, удалив содержимое и поместив файловый указатель в начало файла, либо создать новый файл в случае его отсутствия;
- ‘x+’ – создать файл и открыть его на запись и чтение, поместив файловый указатель в начало файла, либо сгенерировать исключение FileExistsError , если файл с таким именем уже существует;
- ‘a+’ – открыть существующий файл на дозапись и чтение, не удаляя содержимое и поместив файловый указатель в конец файла, либо создать новый файл в случае его отсутствия (при чтении следует не забывать перемещать файловый указатель в нужную позицию файла);
- ‘rb+’ или ‘r+b’ – открыть существующий файл на чтение и запись в бинарном режиме, поместив файловый указатель в начало файла;
- ‘wb+’ или ‘w+b’ – открыть существующий файл на запись и чтение в бинарном режиме, удалив содержимое и поместив файловый указатель в начало файла, либо создать новый файл в случае его отсутствия;
- ‘xb+’ или ‘x+b’ – создать файл и открыть его на запись и чтение в бинарном режиме, поместив файловый указатель в начало файла, либо сгенерировать исключение FileExistsError , если файл с таким именем уже существует;
- ‘ab+’ или ‘a+b’ – открыть существующий файл на дозапись и чтение в бинарном режиме, не удаляя содержимое и поместив файловый указатель в конец файла, либо создать новый файл в случае его отсутствия (при чтении следует не забывать перемещать файловый указатель в нужную позицию файла).
- 0 – отключить буферизацию (только для бинарного режима).
- 1 – построчная буферизация (только для текстового режима).
- n > 1 – размер буфера в байтах.
- -1 – значение по умолчанию: для текстовых файлов, используется построчная буферизация, а двоичные файлы буферизируются кусками фиксированного размера. Для многих систем буфер равен 4096 или 8192 байт. Если же размер буфера определить не удается, используется io.DEFAULT_BUFFER_SIZE .
Стоит заметить, что использовать все параметры функции open() вовсе необязательно, т.к. в большинстве случаев для открытия и работы с файлами достаточно указать путь к файлу, режим работы и кодировку (см. пример №1 ).
Пример №1. Чтение и запись файлов в Python (часть 1).
Как видим, после получения файлового объекта, возвращаемого функцией open() , редактирование данных в открытом файле производится с помощью специального предназначенного для этого набора методов. Перечислим некоторые из них.
- read([size]) – считывает из файла не более size байтов. Если же конец файла EOF достигается до получения указанного размера, метод считывает только доступные байты. В текстовом режиме возвращается строка, в бинарном – байтовый объект.
- readline([size]) – читает и затем возвращает одну целую строку из файла, включая конечный символ \n (если файл открыт в бинарном режиме, метод возвращает байтовый объект). Если указать неотрицательный аргумент size , строка будет считываться частями по size байтов до тех пор, пока не будет достигнут символ новой строки \n . При отрицательном значении size строка будет считываться полностью. В любом случае при достижении конца файла EOF метод вернет пустую строку.
- readlines(sizehint) – возвращает список строк или байтовых объектов файла в зависимости от режима доступа к файлу, включая конечные символы \n строк. Опять же, при достижении конца файла EOF возвращается пустая строка. При наличии необязательного аргумента sizehint читаются целые строки, составляющие приблизительно sizehint байт (округление производится до внутреннего размера буфера).
- write(str) – записывает в файл строку str и возвращает количество записанных байт в виде целого числа. Имейте в виду, что из-за буферизации строка может не отображаться в файле до тех пор, пока не будет вызван метод flush() или close() . Поскольку различные операционные системы имеют собственные соглашения по обозначению конца строки, следует быть внимательным при записи данных в текстовый файл, правильно устанавливая символы конца строки в соответствии с операционной системой, под которой работает скрипт: \n для Unix/Linux , \r\n для Windows и \r для Macintosh .
- writelines(seq) – записывает в файл последовательность строк seq . Последовательностью может быть любой итерируемый объект, содержащий строки в качестве элементов. Следует помнить, что разделители строк при необходимости должны добавляться вручную.
- truncate([size]) – усекает размер файла в байтах по текущему указателю чтения/записи и возвращает size . Если необязательный аргумент size указан, файл усекается до этого размера. Метод не будет работать, если файл открыт в режиме только чтения.
- seek(offset, [whence]) – устанавливает файловый указатель чтения/записи в требуемую позицию offset , которая по умолчанию отсчитывается в байтах от начала файла. Необязательный параметр whence может иметь три значения:
- 0 – указатель будет смещен на offset относительно начала файла (используется по умолчанию);
- 1 – указатель будет смещен на offset относительно текущей позиции указателя;
- 2 – указатель будет смещен на offset относительно конца файла.
Следует всегда закрывать открытый файл после окончания работы с ним, если только файл не был открыт с помощью менеджера контекста with/as , т.к. в этом случае закрытие файла осуществляется в автоматическом режиме (см. пример №2 ).
Пример №2. Чтение и запись файлов в Python (часть 2).
Остальные методы для работы с потоками можно посмотреть в подразделе «io — Core tools for working with streams» стандартной библиотеки.
Стоит добавить, что после открытия текстового файла в соответствующем режиме, запись в файл можно осуществить и при помощи обычной функции print() , передав ей полученный файловый объект в виде значения именованного аргумента file (см. пример №3 ).
Пример №3. Чтение и запись файлов в Python (часть 3).
Модуль pickle: сериализация объектов
Для сериализации и десериализации объектов в Python предназначен модуль pickle , расположенный в подразделе «pickle — Python object serialization» стандартной библиотеки. Он позволяет преобразовывать объекты как в поток байтов (сериализация), так и обратно из байтового состояния в объекты (десериализация). А поскольку поток байтов можно легко записывать в файл, данный модуль широко используется для долговременного хранения и последующей загрузки различных сложных python -объектов. Перечислим основные методы, предоставляемые данным модулем.
- pickle.dump(obj, file, protocol=None, *, fix_imports=True, buffer_callback=None) – сериализует и записывает объект obj в файловый объект file , возвращая затем строку байтов (т.е. pickle.dumps() ). Необязательные аргументы fix_imports , encoding и errors используются для управления поддержкой совместимости потока pickle , генерируемого Python 2 . Нам они не понадобятся, т.к. мы работаем в Python 3 .
- pickle.load(file, *, fix_imports=True, encoding=»ASCII», errors=»strict») – десериализует объект из файлового объекта file и затем возвращает его.
- pickle.dumps(obj, protocol=None, *, fix_imports=True, buffer_callback=None) – сериализует объект (т.е. преобразует в двоичное представление) и затем возвращает его.
- pickle.loads(bytes_object, *, fix_imports=True, encoding=»ASCII», errors=»strict») – десериализует объект из двоичного представления и затем возвращает его.
Посмотрим, как эти методы работают на практике (см. пример №4 ).
Пример №4. Использование модуля pickle (часть 1).
Как видим, благодаря модулю pickle мы с легкостью записали наш словарь в файл, затем извлекли его для изменения и записали обратно. Т.е. по сути мы создали простейшую базу данных для длительного хранения наших объектов. Конечно, работать с объемной базой данных таким образом вряд ли получится, ведь даже для малейших изменений придется читать и перезаписывать весь файл целиком. Однако никто не запрещает, например, создать для каждой записи свой файл и при необходимости извлекать данные по отдельности (см. пример №5 ).
Пример №5. Использование модуля pickle (часть 2).
При желании можно было бы оформить обращение к записям нашей базы данных в виде функций или вообще создать отдельный класс для работы с ней. Главное здесь помнить о том, что не стоит загружать с помощью модуля pickle файлы из ненадёжных источников, т.к. это может привести к непредвиденным и печальным последствиям.
Модуль shelve: key/value хранилище объектов
Если к сохраненным в файлах записям необходим доступ по ключу, вместо модуля pickle удобнее использовать более высокоуровневый инструмент стандартной библиотеки в виде модуля shelve (см. подраздел «shelve — Python object persistence»). Данный модуль реализует постоянное хранилище для произвольных python -объектов, значения которого можно извлекать, используя синтаксис и методы обычного словаря со строковыми ключами.
Осуществляется создание либо открытие такого хранилища с помощью метода shelve.open(filename, flag=’c’, protocol=None, writeback=False) , где
- filename – путь к создаваемому хранилищу и его имя, но без какого-либо расширения. При этом целевой каталог хранилища должен уже существовать, иначе будет получено исключение.
- flag – режим открытия хранилища:
- ‘c’ – хранилище открывается для чтения и записи (используется по умолчанию). Если такого хранилища не существует, то оно вначале создается.
- ‘r’ – хранилище открывается для чтения.
- ‘w’ – хранилище открывается для записи.
- ‘n’ – хранилище открывается для перезаписи. Если такого хранилища не существует, то оно вначале создается.
Результатом вызова shelve.open() является специальный объект для работы с открытым хранилищем, поддерживающий синтаксис и методы обычных словарей и обладающий двумя собственными методами:
- sync() – очищает кеш, записывая все записи из него на диск и синхронизируя хранилище, если хранилище было открыто с флагом writeback=True ;
- close() – синхронизирует и закрывает хранилище или возбуждает ValueError , если оно уже было закрыто.
Рассмотрим использование возможностей модуля shelve для создания постоянного хранилища данных, с последующим добавлением в него новых данных или редактирования/удаления уже существующих (см. пример №6 ).
Пример №6. Использование модуля shelve (часть 1).
Как видим, в простейшем случае для создания хранилища (или открытия уже существующего) нужно передать методу shelve.open() путь к создаваемому хранилищу и его имя, но без какого-либо расширения. В результате в целевом каталоге (либо в каталоге скрипта) интерпретатором будет создано три служебных файла с указанным именем и расширениями .bak , .dat и .dir . При этом целевой каталог хранилища должен существовать еще до начала операции, иначе будет получено исключение. Именно поэтому в нашем примере мы предварительно создали в директории скрипта каталог для хранилища db_devices и только затем указали его в качестве целевого каталога в вызове метода shelve.open() . В результате интерпретатор создал в нем три служебных файла хранилища: db_devices.bak , db_devices.dat и db_devices.dir .
После создания и открытия хранилища можно начинать записывать в него данные, используя для этого синтаксис обычного словаря со строковыми ключами. Здесь главное помнить, что по умолчанию writeback=False , т.е. кеширование данных в памяти, не используется. Поэтому для последующего редактирования изменяемых объектов хранилища их сперва нужно извлечь по ключу, сохранить копию во временной переменной, выполнить над переменной все необходимые операции и в конце записать измененный объект обратно в хранилище (удалив по необходимости и временную копию). В нашем случае последовательность инструкций была следующая: temp_mouse = db_devices[‘mouse’] (мы извлекли из хранилища целевой словарь и присвоили его переменной), temp_mouse[‘кол-во’] = 5 (внесли необходимые изменения в словарь), db_devices[‘mouse’] = temp_mouse (сохранили изменения в хранилище).
Помимо изменения записей открытого хранилища для него доступны также операции по добавлению новых записей и удалению уже существующих. Главное не забывать после завершения всех работ закрывать открытое хранилище с помощью метода close() . Опять же, при использовании менеджера контекста with/as использовать данный метод нет нужды, т.к. при выходе за область его видимости синхронизация с хранилищем и его закрытие будут произведены автоматически.
Далее. Использование параметра обратной записи writeback со значением True может быть весьма удобным, если заранее известно, что количество одновременных запросов к различным записям хранилища будет невелико, как и объем хранимых в них данных. В этом случае все результаты операций будут кешироваться в памяти, что несколько замедлит процесс закрытия хранилища из-за одновременного перемещения данных кеша на диск, но зато хранимые объекты станут доступны для непосредственной обработки с помощью имеющихся у них методов без необходимости создания каких-либо промежуточных копий объектов (см. пример №7 ).
Пример №7. Использование модуля shelve (часть 2).
В общем случае модуль shelve позволяет хранить в файлах не только словари, но и другие сложные объекты, сериализация которых поддерживается модулем pickle (см. пример №8 ).
Пример №8. Использование модуля shelve (часть 3).
Опять же, не стоит без проверки загружать с помощью модулей pickle и shelve файлы из ненадёжных источников, т.к. это может привести к непредвиденным и печальным последствиям в случае передачи злонамеренного кода.
Модуль pathlib: работа с путями
Модуль pathlib представляет собой высокоуровневый инструмент для манипулирования путями файловой системы, по сути объединяя в себе возможности таких модулей, как os , os.path или glob . Ознакомится с документацией по модулю можно в справочнике стандартной библиотеки в подразделе «pathlib — Object-oriented filesystem paths». Здесь же мы рассмотрим наиболее востребованные кроссплатформенные свойства и методы для работы с путями, каталогами и файлами, имеющиеся у класса PurePath и его подкласса Path модуля pathlib .
Объекты pathlib.PurePath() обеспечивают операции обработки пути, которые фактически не обращаются к файловой системе. Поэтому их можно использовать для манипулирования путями Windows на машине Unix или наоборот, не волнуясь при этом за правильную обработку пути. В тоже время подкласс pathlib.Path() представляет пути файловой системы, которые работают с системными вызовами. При создании экземпляра класса pathlib.Path() в зависимости от операционной системы на которой выполняется код, происходит автоматический вызов либо его подкласса pathlib.PosixPath (работа с путями файловой системы, отличной от Windows ), либо pathlib.WindowsPath (работа с путями Windows ). Перечислим основные методы этих классов по работе с путями и рассмотрим конкретные примеры использования предоставляемых возможностей в исходном коде.
- Path.cwd() – возвращает объект пути, представляющий текущий рабочий каталог (похоже на os.getcwd() ).
- Path.home() – возвращает объект пути, представляющий домашний каталог пользователя (похоже на os.path.expanduser() ).
- Path(path).expanduser() – возвращает объект абсолютного пути path , в котором пользовательские конструкции
user в начале пути заменяются на домашний каталог пользователя (похоже на os.path.expanduser() ). Если расширение пути завершается неудачно или путь не начинается с тильды
Пример №9. Использование класса pathlib.Path (часть 1).
- Path(path).exists() – проверяет существование пути path файловой системы, возвращая True или False (похоже на os.path.exists() ). Если путь указывает на символическую ссылку, метод проверяет, указывает ли она на существующий файл или каталог.
- Path(path).is_dir() – возвращает True , если путь path указывает на каталог или символическую ссылку, указывающую на каталог (похоже на os.path.isdir(path) ). Если путь указывает на файл другого типа, вообще не существует или является неработающей символической ссылкой, метод возвращает False . Также метод может вернуть False , если доступ к директории или символической ссылке, указывающей на директорию, отсутствует.
- Path(path).is_file() – все тоже, что и для метода выше, только для файлов (см. пример №10 ). Метод похож на os.path.isfile(path) .
Пример №10. Использование класса pathlib.Path (часть 2).
- Path(path).mkdir(mode=0o777, parents=False, exist_ok=False) – создает по указанному пути path новый каталог (похоже на os.mkdir() ). Метод принимает следующие аргументы:
- mode=0o777 – режим доступа к директории.
- parents=False – по умолчанию при наличии в цепочке отсутствующих каталогов будет вызвано исключение FileNotFoundError . Если необходимо, чтобы отсутствующие каталоги нового пути были созданы, следует указывать parents=True .
- exist_ok=False – по умолчанию в случае существования целевого каталога будет вызвано исключение FileExistsError . При использовании exist_ok=True исключения игнорируются.
Пример №11. Использование класса pathlib.Path (часть 3).
- Path(path).rename(target) – переименовывает/перемещает файл или конечный каталог пути path в target (похоже на os.rename() ). В качестве target разрешается передавать как строку, так и объект пути. Путь path должен существовать, иначе будет брошено исключение. Если путь target уже существует, то в Windows будет брошено исключение, а в Unix путь (файл) будет перезаписан (см. пример №12 ).
- Path(path).replace(target) – заменяет существующий файл или конечный каталог пути path на target (похоже на os.replace() ). В качестве target разрешается передавать как строку, так и объект пути. Путь path должен существовать, иначе будет брошено исключение. Если путь target уже существует, то в Windows будет брошено исключение, а в Unix путь (файл) будет перезаписан. Основное отличие этого метода от Path(path).rename(target) заключается в том, что в ходе замены (переименования) файла данные в нем будут безвозвратно удалены.
Пример №12. Использование класса pathlib.Path (часть 4).
- Path(path).open(mode=’r’, buffering=-1, encoding=None, errors=None, newline=None) – открывает файл, на который указывает путь path , и возвращает соответствующий файловый объект для доступа к нему, как это делает встроенная функция open().
- Path(path).write_text(data, encoding=None, errors=None, newline=None) – открывает файл для записи в текстовом режиме, записывает в него данные data и закрывает его, возвращая количество записанных байт. Если файл с таким именем уже существует, он перезаписывается. Необязательные параметры имеют тот же смысл, что и для встроенной функции open() .
- Path(path).read_text(encoding=None, errors=None) – открывает, читает и затем закрывает текстовый файл, возвращая прочитанную строку.
- Path(path).write_bytes(data) – открывает файл для записи в бинарном режиме, записывает в него данные data и закрывает его, возвращая количество записанных байт. Если файл с таким именем уже существует, он перезаписывается.
- Path(path).read_bytes() – открывает, читает и затем закрывает двоичный файл, возвращая байтовый объект (см. пример №13 ).
Пример №13. Использование класса pathlib.Path (часть 5).
- Path(path).glob(pattern) – возвращает список всех файлов, соответствующих заданному шаблону pattern и расположенных в каталоге, указанном в пути path . Начиная с Python 3.11 метод возвращает только каталоги, если шаблон pattern заканчивается разделителем компонентов пути ( os.sep или os.altsep ). Если в шаблоне использовать комбинацию ** , то будет осуществляться рекурсивный обход в глубину каталога, указанного в пути path , и всех его подкаталогов. Это удобно, но в больших деревьях каталогов может занимать слишком много времени.
- Path(path).rglob(pattern) – производит рекурсивный поиск файлов аналогично предыдущему методу за счет автоматического добавления **/ в начале шаблона pattern .
- Path(path).iterdir() – возвращает итератор объектов в каталоге, на который указывает путь path (см. пример №14 ).
Пример №14. Использование класса pathlib.Path (часть 6).
Модуль shutil: операции над файлами и каталогами
Модуль shutil содержит набор высокоуровневых функций для обработки файлов и каталогов, позволяющих, например, копировать, перемещать, удалять и даже архивировать их. Опять же, ознакомится с документацией по модулю можно в справочнике стандартной библиотеки в подразделе «shutil — High-level file operations». Здесь же мы рассмотрим лишь наиболее востребованные кросплатформенные свойства и методы для операций над файлами и каталогами.
- shutil.copyfileobj(fsrc, fdst[, length]) – копирует содержимое файлового объекта fsrc в другой файловый объект fdst . Необязательный параметр length — размер буфера при копировании (используется для предотвращения чтения в память огромных файлов целиком). Следует помнить, что копирование осуществляется с текущей позиции указателя в fsrc , а не с начала файла.
- shutil.copyfile(src, dst, follow_symlinks=True) – копирует содержимое файла src без метаданных в файл dst и возвращает dst . Аргументы src и dst должны быть строками, содержащими пути к файлам. При чем dst должен быть полным именем файла. Если указать существующий файл dst , он будет перезаписан. Если src и dst представляют собой один и тот же файл, будет брошено исключение shutil.SameFileError . Если аргумент follow_symlinks=False , а src является ссылкой на файл, то будет создана новая символическая ссылка вместо копирования файла, на который эта символическая ссылка указывает.
- shutil.copy(src, dst, follow_symlinks=True) – копирует содержимое файла src вместе с правами доступа в файл или каталог dst и возвращает путь к местонахождению нового скопированного файла. Если dst является каталогом, файл будет скопирован со своим прежним именем. Если аргумент follow_symlinks=False , а src – это ссылка, то dst также будет ссылкой. Если же follow_symlinks=True , а src – это ссылка, то dst будет копией файла, на который ссылается src .
- shutil.copy2(src, dst, follow_symlinks=True) – работает как copy() , но пытается копировать вообще все метаданные.
- shutil.copymode(src, dst, follow_symlinks=True) – копирует права доступа из src в dst . Содержимое файла, владелец и группа не затрагиваются.
- shutil.copystat(src, dst, follow_symlinks=True) – копирует права доступа, время последнего доступа и последнего изменения, а также флаги src в dst . Содержимое файла, владелец и группа не затрагиваются.
- shutil.chown(path, user=None, group=None) – меняет владельца и/или группу у файла или каталога.
- shutil.ignore_patterns(*patterns) – создает функцию, которая позволяет выборочно копировать файлы из каталогов, игнорируя файлы и каталоги в соответствии с одним из предоставленных шаблонов *patterns типа glob.glob() . Созданная функция может быть использована в качестве значения аргумента ignore для copytree() .
- shutil.copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, ignore_dangling_symlinks=False, dirs_exist_ok=False) – рекурсивно копирует дерево каталогов src в каталог dst и возвращает каталог назначения. Аргумент dirs_exist_ok указывает, следует ли вызвать исключение в случае, если целевой каталог dst или какой-либо отсутствующий родительский каталог уже существует. Права и времена у каталогов копируются с помощью функции copystat() , а файлы по умолчанию копируются с помощью функции copy2() , хотя в аргумент copy_function разрешается передавать любую функцию, поддерживающую такую же сигнатуру, например shutil.copy() . По умолчанию, когда symlinks=False , копируются как содержимое, так и метаданные файлов, на которые указывали ссылки. При этом, если файл, на который указывает ссылка, не существует, в список ошибок в исключении shutil.Error в конце копирования будет добавлено исключение, скрыть которое можно путем установки флага ignore_dangling_symlinks=True . Если аргумент symlinks=True , ссылки в дереве src станут ссылками в dst , а метаданные будут скопированы настолько, насколько это возможно. Если значение аргумента ignore не равно None , то это должен быть объект функции, принимающей в качестве аргументов имя целевого каталога dst и список его содержимого, возвращаемый функцией os.listdir() . Поскольку copytree() вызывается рекурсивно, функция в ignore будет вызываться один раз для каждого вложенного копируемого каталога. Кроме того, переданная в ignore функция должна возвращать последовательность имен каталогов и файлов относительно текущего каталога, то есть подмножества элементов во втором аргументе. Эти имена будут игнорироваться в процессе копирования.
- shutil.move(src, dst, copy_function=copy2) – рекурсивно перемещает файл или каталог из src в другое место dst и возвращает место назначения dst . Если dst является существующим каталогом, то src перемещается внутрь каталога. Если же цель dst существует, но не является каталогом, то она может быть перезаписана.
- shutil.rmtree(path, ignore_errors=False, onerror=None, *, dir_fd=None) – рекурсивно удаляет все дерево каталогов. При этом путь path должен указывать именно на каталог, а не символическую ссылку на каталог. Если указать ignore_errors=True , то возникшие в результате неудачного удаления ошибки будут игнорироваться. По умолчанию, когда ignore_errors=False , такие ошибки вызывают исключения или обрабатываются путем вызова обработчика, если он используется в onerror .
- shutil.which(cmd, mode=os.F_OK | os.X_OK, path=None) – возвращает путь к исполняемому файлу, который будет запущен при вызове командного файла cmd (путь к нему передается в виде строки). Если никакая команда не будет вызвана, функция вернет None . Аргумент mode – это права доступа, требующиеся от файла. По умолчанию проверяется только существование файла и является ли он исполняемым.
- shutil.disk_usage(path) – возвращает статистику использования диска по указанному пути в виде именованного кортежа с атрибутами total , used и free , представляющих осответственно общий объем диска, используемый объем и объем свободного пространства в байтах. Путь path может быть файлом или каталогом (см. пример №15 ).
Пример №15. Использование модуля shutil (часть 1).
Помимо функций для работы с обычными файлами и каталогами модуль shutil предоставляет также несколько высокоуровневых функций, основанных на возможностях модулей zipfile и tarfile, для создания и чтения архивированных и сжатых файлов. Пробежимся по ним.
- shutil.make_archive(base_name, format[, root_dir[, base_dir[, verbose[, dry_run[, owner[, group[, logger]]]]]]]) – создает архивный файл, например zip или tar и возвращает его имя. Первые два аргумента обязательны для передачи, остальные могут быть опущены:
- base_name – путь к создаваемому архиву с указанием в конце пути имени файла архива без расширения, т.к. оно зависит от выбранного формата (например, ‘./dir_1/dir_2’ ).
- format – формат создаваемого архива: ‘zip’ , ‘tar’ или ‘gztar’ , если доступен модуль zlib; bztar , если доступен модуль bz2; xztar , если доступен модуль lzma.
- root_dir – корневой каталог, относительно которого будет строиться путь к архивируемому файлу или каталогу base_dir (по умолчанию используется текущий каталог).
- base_dir – путь к существующему файлу или каталогу, который требуется заархивировать, отсчитываемый относительно корневого каталога root_dir ; если путь не указывается, то в архив будет помещено все содержимое каталога root_dir ; если указать неверный путь, будет брошено соответствующее исключение.
- verbose – устаревший, больше не используется и не рекомендуется.
- dry_run – если данный аргумент имеет значение True , архив не создается, но выполняемые операции записываются в журнал.
- owner – используется при создании архива tar . По умолчанию используется текущий владелец.
- group – используется при создании архива tar . По умолчанию используется текущая группа.
- logger – данный аргумент должен быть объектом, совместимым с PEP 282 , обычно это экземпляр logging.Logger.
Пример №16. Использование модуля shutil (часть 2).
Краткие итоги параграфа
- Файл – это именованная область данных на носителе информации. При этом большинство операционных систем в целях однозначности не допускает использование двух файлов с полностью идентичными именами в одном каталоге.
- Чтобы помочь системе определить тип файла и, соответственно, приложение для работы с ним, в имени файла обычно указывается его расширение, которое отделяется от остальной части имени точкой. Примерами расширений файлов могут служить .txt – обычный текстовый файл, .py – файл с кодом Пайтона и огромное число других расширений.
- Когда файлов становится слишком много, возникает необходимость их упорядочивания и группировки. Для этих целей используются каталоги или директории, которые представляют собой специальные объекты файловой системы, используемые для упрощения организации файлов. В графическом пользовательском интерфейсе каталоги также называют папками. В любом случае каталоги представляет собой файлы, содержащие записи о входящих в них файлах или других каталогах. При этом каталог, прямо или косвенно включающий в себя все прочие каталоги и файлы программы, называют корневым. А каталог, в котором находится текущий каталог, называют родительским каталогом.
- Для чтения и записи файлов в Python предназначена встроенная функция open() , которая возвращает специальный итерируемый файловый объект, связанный с целевым файлом и обладающий набором методов для чтения, записи и редактирования открытого файла. Сюда относятся, например, методы: read() (читает заданное количество байт из файла), readline() (чтение одной строки), readlines() (читает файл в список строк), write() (записывает строку в файл), writelines() (записывает в файл переданную последовательность строк), close() (закрывает файл).
- Для сериализации и десериализации объектов в Python предназначен модуль pickle стандартной библиотеки. Он позволяет преобразовывать объекты как в поток байтов (сериализация), так и обратно из байтового состояния в объекты (десериализация). А поскольку поток байтов можно легко записывать в файл, данный модуль широко используется для долговременного хранения и последующей загрузки различных сложных python -объектов. Запись объектов в файл осуществляется с помощью функции pickle.dump() , а чтение из файла – pickle.load() .
- Если к сохраненным в файлах записям необходим доступ по ключу, вместо модуля pickle удобнее использовать более высокоуровневый инструмент стандартной библиотеки в виде модуля shelve . Данный модуль реализует постоянное хранилище для произвольных python -объектов, значения которого можно извлекать, используя синтаксис и методы обычного словаря со строковыми ключами. Осуществляется открытие такого хранилища с помощью метода shelve.open() .
- Для манипулирования путями файловой системы предназначен модуль pathlib , который представляет собой высокоуровневый инструмент объединяющий в себе возможности таких модулей, как os , os.path или glob . С его помощью, например, легко определять текущий рабочий каталог ( Path.cwd() ), проверять является путь каталогом ( Path(path).is_dir() ), файлом ( Path(path).is_file() ) и существует ли он вообще ( Path(path).exists() ), создавать директории ( Path(path).mkdir() ) и файлы ( Path(path).touch() ), а также удалять их ( Path(path).rmdir() и Path(path).unlink() ), открывать файлы для чтения и записи ( Path(path).open() ), осуществлять поиск каталогов и файлов по заданному шаблону ( Path(path).glob(pattern) ) и многое другое.
- Также нами был рассмотрен модуль shutil , содержащий набор высокоуровневых функций для обработки файлов и каталогов. В частности модуль дает возможность копировать содержимое файлов ( shutil.copyfileobj() и shutil.copyfile() ), копировать сами файлы и каталоги ( shutil.copy() и shutil.copytree() ), перемещать их ( shutil.move() ), удалять целые деревья каталогов вместе с файлами ( shutil.rmtree() ), а также архивировать их ( shutil.make_archive() и shutil.unpack_archive() ) и т.д.
Вопросы и задания для самоконтроля
1. Что такое файл? Для чего нужны расширения файлов? Показать решение.
Ответ. Файл – это именованная область данных на носителе информации. Имена файлов нужны для того, чтобы точно знать, к какой области данных носителя информации осуществляется запрос. Что касается расширения файла, то оно указывается после точки и призвано помочь системе определить тип файла, а значит и приложение для работы с ним.
2. Для чего нужны каталоги? Какой каталог приложения называют корневым? Какой каталог по отношению к данному является родительским? Показать решение.
Ответ. Каталоги нужны для создания упорядоченной структуры файлов в файловой системе и, в частности, в многофайловой программе. Каталог, прямо или косвенно включающий в себя все прочие каталоги и файлы программы, называется корневым. Родительским называется каталог, в котором находится текущий каталог.
3. Опишите режимы открытия файлов с помощью встроенной функции open() . Показать решение.
Ответ. Режим открытия файла задается аргументом mode , который в качестве строки может принимать следующие значения:
- ‘r’ – открыть файл на чтение (значение по умолчанию);
- ‘w’ – открыть файл на запись (содержимое файла удаляется, а если его нет, то создается новый);
- ‘x’ – создать файл и открыть его на запись либо сгенерировать исключение FileExistsError , если файл с таким именем уже существует;
- ‘a’ – открыть файл на дозапись (содержимое файла не удаляется, а запись новой информации осуществляется в конец файла);
- ‘b’ – открыть файл в бинарном режиме; используется как дополнительный флаг, например, ‘rb’ , ‘wb’ или ‘ab’ ;
- ‘t’ – открыть файл в текстовом режиме; используется как дополнительный флаг по умолчанию;
- ‘+’ – открыть файл на чтение и запись одновременно; используется как дополнительный флаг, например, ‘r+’ или ‘w+’ (файловый указатель помещается в начало файла, если он существует, либо создается новый файл для чтения и записи), ‘a+’ (файловый указатель помещается в конец файла, если он существует, либо создается новый файл для чтения и дозаписи), ‘rb+’ , ‘wb+’ или ‘ab+’ .
4. Как с помощью встроенной функции open() прочитать небольшой текстовый файл целиком, только первую строку? Показать решение.
Ответ. Необходимо открыть файл в режиме чтения с помощью встроенной функции open() , получив соответствующий файловый объект, после чего использовать метод read() этого файлового объекта для чтения файла целиком или метод readline() для чтения первой строки. В конце нужно не забыть закрыть файл с помощью метода close() .
5. Как с помощью встроенной функции open() дописать строку в конец файла? Показать решение.
Ответ. Необходимо воспользоваться встроенной функцией open() в режиме дозаписи ‘a’ , получив соответствующий файловый объект, после чего использовать метод write() этого файлового объекта для дозаписи в конец файла требуемой строки. После завершения записи следует закрыть файл с помощью метода close() .
6. Перепишите представленный код с использованием менеджера контекста. Показать решение.
Модуль Pickle в Python
Pickling – популярный способ консервирования продуктов. Согласно Википедии, это тоже довольно древняя процедура – хотя происхождение маринования неизвестно, древние месопотамцы, вероятно, использовали этот процесс 4400 лет назад. Поместив продукт в определенный раствор, можно увеличить срок его хранения. Другими словами, это метод, который позволяет нам хранить пищу для последующего употребления.
Если вы разработчик Python, однажды вам может понадобиться способ хранения ваших объектов для последующего использования.
Что такое сериализация в Python?
Сериализация в Python – это процесс преобразования объектов или структур данных в байтовые потоки или строки. Поток байтов – это один байт состоит из 8 бит нулей и единиц. Эти байтовые потоки затем можно легко сохранить или передать. Это позволяет разработчикам сохранять, например, данные конфигурации или прогресс пользователя, а затем сохранять их (на диске или в базе данных) или отправлять в другое место.
Объекты в Python также можно сериализовать с помощью модуля под названием Pickle.
Одним из основных отличий маринования объектов в Python от маринования овощей является неизбежное и необратимое изменение вкуса и текстуры маринованной пищи. Между тем, маринованные объекты можно легко вернуть в их первоначальную форму. Кстати, этот процесс широко известен, как десериализация.
Pickling (или сериализацию в целом) не следует путать со сжатием. Целью Pickling является перевод данных в формат, который может быть перенесен из ОЗУ на диск. С другой стороны, сжатие – это процесс кодирования данных с использованием меньшего количества бит (для экономии места на диске).
Сериализация особенно полезна в любом программном обеспечении, где важно иметь возможность сохранить некоторый прогресс на диске, выйти из программы, а затем загрузить прогресс обратно после повторного открытия программы. Видеоигры могут быть наиболее интуитивным примером полезности сериализации, но есть много других программ, в которых сохранение и загрузка данных или прогресса пользователя имеет решающее значение.
Сравнение pickle и JSON
Возможно, вы слышали о JSON (нотация объектов JavaScript), который является популярным форматом, который также позволяет разработчикам сохранять и передавать объекты, закодированные в виде строк. Этот метод сериализации имеет некоторые преимущества перед сохранением. Формат JSON удобочитаем, не зависит от языка и быстрее, чем pickle.
Однако у него есть и некоторые важные ограничения. Что наиболее важно, по умолчанию только ограниченное подмножество встроенных типов Python может быть представлено JSON. С помощью Pickle мы можем легко сериализовать очень широкий спектр типов Python и, что важно, настраиваемые классы. Это означает, что нам не нужно создавать настраиваемую схему (как мы делаем для JSON) и писать сериализаторы и парсеры, подверженные ошибкам. С Pickle вся тяжелая работа будет сделана за вас.
Что можно сериализовать?
- Все собственные типы данных, поддерживаемые Python (логические, None, целые числа, числа с плавающей запятой, комплексные числа, строки, байты, байтовые массивы).
- Словари, наборы, списки и кортежи – если они содержат выбираемые объекты.
- Функции и классы, определенные на верхнем уровне модуля.
Важно помнить, что травление не является независимым от языка методом сериализации, поэтому ваши консервированные данные могут быть извлечены только с помощью Python. Более того, важно убедиться, что объекты обрабатываются с использованием той же версии Python, которая будет использоваться для их выделения. В этом случае смешивание версий может вызвать множество проблем.
Кроме того, функции выбираются по ссылкам на их имена, а не по их значениям. Полученный в результате Pickling не содержит информации о коде или атрибутах функции. Следовательно, вы должны убедиться, что среда, в которой функция не выбрана, может импортировать функцию. Другими словами, если мы выберем функцию, а затем удалим ее в среде, где она либо не определена, либо не импортирована, возникнет исключение.
Также очень важно отметить, что маринованные предметы могут использоваться специально. Например, извлечение данных из ненадежного источника может привести к выполнению вредоносного кода.
Использование модуля
В следующем очень простом примере показаны основы использования модуля Pickle в Python 3:
Во-первых, мы должны импортировать модуль pickle, что выполняется в строке 1. В строке 3 мы определяем простой список из трех элементов, который будет обработан.
В строке 5 мы указываем, что имя нашего выходного файла pickle будет test_pickle.pkl. Используя параметр wb, мы сообщаем программе, что хотим записать (w) двоичные данные (b) внутри нее (потому что мы хотим создать поток байтов). Обратите внимание, что расширение pkl не обязательно – мы используем его в этом руководстве, потому что это расширение включено в документацию Python.
В строке 6 мы используем метод pickle.dump(), чтобы собрать наш тестовый список и сохранить его в файле test_pickle.pkl.
Я рекомендую вам попробовать открыть сгенерированный файл pickle в текстовом редакторе. Вы быстро заметите, что поток байтов определенно не является удобочитаемым форматом.
Распаковка
Теперь давайте раскроем содержимое тестового файла pickle и вернем наш объект к его исходной форме.
Как видите, эта процедура не сложнее, чем когда мы мариновали объект. В строке 3 мы снова открываем наш файл test_pickle.pkl, но на этот раз наша цель – прочитать (r) двоичные данные (b), хранящиеся в нем.
Затем, в строке 5, мы используем метод pickle.load(), чтобы распаковать наш список и сохранить его в переменной unpickled_list.
Затем вы можете распечатать содержимое списка, чтобы убедиться, что он идентичен списку, который мы выбрали в предыдущем примере. Вот результат выполнения приведенного выше кода:
Сериализация и распаковка нестандартных объектов
Как я упоминал ранее, используя Pickle, вы можете сериализовать свои собственные настраиваемые объекты. Взгляните на следующий пример:
Как видите, этот пример почти такой же простой, как и предыдущий. Между строками 3 и 7 мы определяем простой класс, который содержит один атрибут и один метод, который изменяет этот атрибут. В строке 9 мы создаем экземпляр этого класса и сохраняем его в переменной cucumber, а в строке 10 мы устанавливаем цвет его атрибута на «зеленый».
Затем, используя те же функции, что и в предыдущем примере, мы сериализуем и отделяем наш только что созданный объект. Выполнение приведенного выше кода приводит к следующему выводу:
Помните, что мы можем распаковать объект только в среде, где класс Veggy либо определен, либо импортирован. Если мы создадим новый скрипт и попытаемся выделить объект без импорта класса Veggy, мы получим «AttributeError». Например, выполните следующий скрипт:
В выводе приведенного выше скрипта вы увидите следующую ошибку:
Заключение
Как видите, благодаря модулю Pickle сериализация объектов Python довольно проста. В наших примерах мы выбрали простой список, но вы можете использовать тот же метод для сохранения большого спектра типов данных Python, если вы убедитесь, что ваши объекты содержат только другие выбираемые объекты.
У Pickling есть некоторые недостатки, самый большой из которых может заключаться в том, что вы можете распаковать свои данные только с помощью Python – если вам нужно кросс-языковое решение, JSON определенно лучший вариант. И, наконец, помните, что сериализованные объекты можно использовать для переноса кода, который вы не обязательно хотите выполнять.