Save a Dictionary to a File in Python

This tutorial explains multiple methods to save a dictionary to a file in Python language. Methods include:
- dump() function of pickle module of Python
- save() function of NumPy library
- dump() function of Python json module.
Save a Dictionary to File in Python Using the dump Function of the pickle Module
Please enable JavaScript
The code example below shows how we can use the dump() function of the pickle module to save the dictionary and read a dictionary from the saved file using the load() function. The dump() function of the pickle module needs the dictionary which we want to save, and the file object as parameters to save the dictionary as a .pkl file.
The below code example shows how to read the dictionary saved in a file, using the load() function. The load() function needs a file object as a parameter to load the dictionary from the .pkl file.
Save a Dictionary to File in Python Using the save Function of NumPy Library
The save() function of the NumPy library can also save a dictionary in a file. In order to save the dictionary as a .npy file, the save() function requires the file name and dictionary which we want to save, as parameters to save the dictionary to a file.
The code example shows how to read the Python dictionary saved as .npy file. The load() function of NumPy library requires the file name and need to set allow_pickle parameter as True to load the saved dictionary from .npy file.
Save a Dictionary to File in Python Using the dump Function of the json Module
Another method to save a dictionary to file in Python is to use the dump() function of the json module. It also needs dict variable which we want to save, and file object as parameters to save the dictionary as .json file
Code example to read the dictionary saved as a file using the load function of the json module is shown below. The load() function needs file object as parameter to load the dictionary from the .json file.
Write Dictionary to text file in Python
In this post, we will learn how to Write a Dictionary to a text file in Python by using different ways with code examples. Python dictionary is a data structure that stores data in key-value pairs.
1. Write dictionary to file using For loop
The simple method to write a dictionary to a text file is by using the ‘for’ loop. First Open the file in write mode by using the File open() method.
Then Get the key and value pair using the dictionary items() method from the Dictionary. Iterate over the key values of the dictionary using the ‘for’ loop and write key and value to a text file by using the write() method.
Program Example
Output
It will create a file with the name (DictFile.txt) in the current directory and write the data as shown below.
Program for Writing and Reading a dictionary to file
Output :
The file will get created in the current directory with the following data format.
3. JSON.dump() to write a dictionary to a text file
The JSON is a text format that is language-independent. It is very easy to read and write, the machine can easily parse it and generate it. We are using the JSON module dump() method.
- Import the JSON Module.
- open the file in write mode using with statement “with open(“DictFile.txt”,”w”) as file:”
- Write the dictionary to file using write(json.dumps(dict_students)) method.
Output
4. Save dictionary to text with file.write()
In this example, we are saving a dictionary to a text file using the file.write() method.
Opening the file in write mode using the with statement. When using the with statement then there is no need to close the file. It is automatically handled by the compiler.
Then we are Writing the whole dictionary at one go by using the File. write() method. And using the str() method to convert a dictionary to string to write to file.
Program to save Dictionary to Text file
Output
5. Write dictionary to text file by dict.keys()
In this example, we are getting all dictionary keys by using the dictionary keys() method and iterating over all keys using for loop.
Writing key and values as a string by using this format “str(key)+” “+str(dict_students[key])” to file.We can change the format of the string as per requirement. Finally closing the file using the close() method.
Output:
The file will get created with the following data in the current directory.
Instead of keys(), we can use items() to write dictionary to file. Let us understand with an example
Output
Summary
In this post, we have learned 5 different ways to Write Dictionary to a text file in Python with code examples.
Файлы и каталоги в 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. Перепишите представленный код с использованием менеджера контекста. Показать решение.