Основы работы с файлами в Python

Содержание
Введение
Создать
open(): Открыть
close(): Закрыть
closed: Закрыт ли файл
with: Менеджер контекста
Очистить файл
read(): чтение файла
readline() и readlines(): построчное чтение
Копировать файл
write(): Запись в файл
Дописать к файлу
writelines()
Похожие статьи

Введение

В этой статье вы узнаете как организовать работать с файлами в Python 3.

Создайте файл files.py и копируйте туда код из примеров.

Запустить файл можно командой

python3 files.py

Создать

Создать файл можно командой open

Опции:

r  чтение

rb чтение в бинарном режиме

rt чтение в текстовом режиме

только запись.

wb запись в бинарном режиме

wt запись в текстовом режиме

w+ запись и чтение

запись в конец файла - сохранит данные, которые были в файле

b - это селектор бинарного режима

t - это селектор текстового режима

Любая опция с w перезапишет существующий файл - будьте внимательны!

Пример:

f = open("log.txt","w+")

Кодировка

По умолчанию в open() используется кодировка которую возвращает вызов locale.getencoding()

In text mode, if encoding is not specified the encoding used is platform dependent: locale.getencoding() is called to get the current locale encoding.

import locale print(locale.getencoding())

cp1252

Это может отличаться от того, что возвращает sys.getdefaultencoding() или sys.stdout.encoding

docs.python.org/3/library/codecs.html#standard-encodings

import sys print(sys.getdefaultencoding())

utf-8

Открыть файл

Синтаксис:

open(path_to_file, mode, encoding)

Про encoding можно прочитать здесь

Чтобы открыть файл для чтения выполните

f = open("log.txt","r")

Если файл log.txt не существует, он не будет создан

raceback (most recent call last): File "files.py", line 1, in <module> f = open('log.txt', 'r') FileNotFoundError: [Errno 2] No such file or directory: 'log.txt'

Класс к которому принадлежит объект открытого файла называется _io.TextIOWrapper

print(type(f))

<class '_io.TextIOWrapper'>

Закрыть файл

Чтобы закрыть файл выполните

f.close()

Закрытие файла не удаляет ссылку на него.

f = open("log.txt","r") print(type(f)) f.close() print(type(f))

<class '_io.TextIOWrapper'> <class '_io.TextIOWrapper'>

Ссылка остаётся, но так как файл закрыт с ним почти ничего нельзя сделать

f = open("log.txt","r") f.close() contents = f.read()

Traceback (most recent call last): File "C:\Users\Andrei\close.py", line 4, in <module> contents = f.read() ^^^^^^^^ ValueError: I/O operation on closed file.

Закрыт ли файл

Для того чтобы проверить закрыт ли файл используется атрибут closed. Обратимся к нему после открытия файла. Ожидаемый результат - False

f = open("log.txt","r") print(f.closed)

False

Атрибут closed есть у объектов типа _io.TextIOWrapper поэтому проверять закрыта ли строка или что-то подобное смысла нет

s = "" print(s.closed)

Traceback (most recent call last): File "C:\Users\Andrei\closed.py", line 2, in <module> print(s.closed) ^^^^^^^^ AttributeError: 'str' object has no attribute 'closed'

Так как метод close() не удаляет ссылку на файл, можно обратиться к атрибуту closed и после закрытия файла. Ожидаемый результат - True

f = open("log.txt","r") print(f.closed) f.close() print(f.closed)

False True

Менеджер контекста

Предпочтительнее использовать менеджер контекста для работы с файлами

Как только вы выйдете из блока в котором открыт файл - он автоматически закроется

with open('log.txt', 'r') as f: pass print(f.closed)

True

С помощью функции type() легко убедиться, что объект, который получается в результате использования with имеет тип _io.TextIOWrapper - тот же тип который мы получали с помощью обычного open()

Для полноты картины, изучим доступные методы и атрибуты, с помощью dir()

with open('log.txt', 'r') as f: print(type(f)) print(dir(f))

<class '_io.TextIOWrapper'> ['_CHUNK_SIZE', '__class__', '__del__', '__delattr__', '__dict__', '__dir__', '__doc__', '__enter__', '__eq__', '__exit__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_checkClosed', '_checkReadable', '_checkSeekable', '_checkWritable', '_finalizing', 'buffer', 'close', 'closed', 'detach', 'encoding', 'errors', 'fileno', 'flush', 'isatty', 'line_buffering', 'mode', 'name', 'newlines', 'read', 'readable', 'readline', 'readlines', 'reconfigure', 'seek', 'seekable', 'tell', 'truncate', 'writable', 'write', 'write_through', 'writelines']

Так как у объекта класса _io.TextIOWrapper есть метод next() по нему удобно итерировать.

Рассмотри файл sites.txt

www.heihei.ru www.testsetup.ru www.topbicycle.ru

И пройдём по нему с помощью next()

with open('sites.txt', 'r') as f: print(next(f)) print(next(f)) print(next(f)) print(next(f))

www.heihei.ru www.testsetup.ru www.topbicycle.ru Traceback (most recent call last): File "/mnt/c/Users/Andrei/open_ex.py", line 5, in <module> print(next(f)) ^^^^^^^ StopIteration

next() работает до тех пор, пока элементы не закончатся и затем поднимает StopIteration исключение.

Будем рассматривать примеры работы с файлами как с использованием менеджера контекста так и без него.

read(): чтение файла

Получать данные из файла можно с помощью read()

В неё можно передавать аргумент типа int и тогда будет возвращено соответсвующее количество байт содераждания файла.

Прочитать содержимое файла

with open('sites.txt', 'r') as f: f_contents = f.read() print(f_contents)

www.heihei.ru www.testsetup.ru www.topbicycle.ru

Рассмотрим файл sites.md который состоит из одной строки

topbicycle.ruheihei.rueth1.ru

>>> f = open('sites.md', mode='rt', encoding='utf-8') >>> f.read(3)

'top'

>>> f.read(7)

'bicycle'

>>> f.read(3)

'.ru'

Чтобы получить всё что осталось в файл нужно вызвать read() без аргументов.

>>> f.read()

'heihei.rueth1.ru'

Если вызвать read() ещё раз, вернётся пустая строка

>>> f.read()

''

В данный момент указатель стоит на конце файла, но его можно переместить с помощью seek()

Прочитать определённое количество символов

with open('sites.md', 'r') as f: f_contents = f.read(20) print(f_contents)

www.eth1.ru www.heihe

Если выполнять эту команду последовательно - будут прочитаны следующие символы

with open('sites.md', 'r') as f: f_contents = f.read(20) print(f_contents, end = '') f_contents = f.read(20) print(f_contents, end = '')

www.eth1.ru www.heihei.ru www.topbicycle.

Цикл для произвольного количества символов .read

with open('sites.md', 'r') as f: size_to_read = 10 f_contents = f.read(size_to_read) while len(f_contents) > 0: print(f_contents, end = '') f_contents = f.read(size_to_read)

www.eth1.ru www.heihei.ru www.topbicycle.ru

Выражение f_contents = f.read(size_to_read) нужно для того, чтобы когда файл закончится и f.read(size_to_read) станет нулем len(f_contents) тоже станет нулем и цикл завершится

Очистить файл

>>> f = open('sites.md', mode='w', encoding='utf-8') >>> f.write('')

0

>>> f.close() >>> exit()

readline(): построчное чтение

Метод readline() выводит содержимое построчно.

А метод readlines() выводит все строки в виде списка

Рассмотрим файл sites.md который состоит из трёх строк

topbicycle.ru heihei.ru eth1.ru

>>> f = open('sites.md', mode='rt', encoding='utf-8') >>> f.readline()

'www.topbicycle.ru\n'

>>> f.readline()

'www.heihei.ru\n'

>>> f.readline()

'eth1.ru'

Когда строки закончатся readline() будет возвращать не ошибку, а просто пустую строку

>>> f.readline()

''

>>> type(f.readline())

<class 'str'>

Если нужно снова читать сначала пригодится метод seek() про которой можно прочитать в статье «Дополнительные приёмы работы с файлами»

>>> f.seek(0)

0

>>> f.readline()

'www.topbicycle.ru\n'

>>> f.close()

Строки по одной с помощью readline() в скрипте

with open('sites.md', 'r') as f: f_contents = f.readline() print(f_contents) f_contents = f.readline() print(f_contents)

www.eth1.ru www.heihei.ru

Убрать переходы на новую строку можно с помощью end=''

with open('sites.md', 'r') as f: f_contents = f.readline() print(f_contents, end = '') f_contents = f.readline() print(f_contents, end = '')

www.eth1.ru www.heihei.ru

Цикл для построчного вывода без использования readline()

with open('sites.md', 'r') as f: for line in f: print(line, end = '')

www.eth1.ru www.heihei.ru www.topbicycle.ru

В качестве альтернативы можно использовать sys.stdout.write()

Про передачу аргументов из терминала вы можете прочитать в статье sys.argv[]

# files.py import sys f = open(sys.argv[1], mode='rt', encoding='utf-8') for line in f: sys.stdout.write(line) f.close()

python files.py sites.md

www.eth1.ru www.heihei.ru www.topbicycle.ru

readlines()

Метод readlines() выводит все строки в виде списка

>>> f.readlines()

['www.topbicycle.ru\n', 'www.heihei.ru\n', 'eth1.ru']

>>> f.close()

Все строки с символом перехода на новую строку - readlines

with open('sites.md', 'r') as f: f_contents = f.readlines() print(f_contents)

['www.eth1.ru\n', 'www.heihei.ru\n', 'www.topbicycle.ru\n']

Имя файла

Пример программы, которая выводит на экран имя файла и режим, в котором он открыт

f = open('log.txt', 'r') print(f.name) print(f.mode) f.close()

Если файл log.txt существует, то в терминале вы увидите

log.txt
r

РЕКЛАМА от Яндекса. Может быть недоступна в вашем регионе

Конец рекламы от Яндекса. Если в блоке пусто считайте это рекламой моей телеги

Копирование файлов

Текстовые файлы

Их можно копировать построчно

with open('sites.md', 'r') as rf: with open('sites_copy.txt', 'w') as wf: for line in rf: wf.write(line)

cat sites_copy.txt

www.eth1.ru www.heihei.ru www.topbicycle.ru

Изображения

Их тоже можно копировать построчно, но открывать и записывать нужно в побитовом режиме. То есть нужно добавлять опцию b

Скачайте изображение велосипеда с сайта TopBicycle.ru или возьмите любую другую картинку

wget https://topbicycle.ru/b/img/stels_pilot_950_MD_26.jpg
ls

stels_pilot_950_MD_26.jpg

with open('stels_pilot_950_MD_26.jpg', 'rb') as rf: with open('stels_pilot_950_MD_26_copy.jpg', 'wb') as wf: for line in rf: wf.write(line)

python3 files.py
ls

stels_pilot_950_MD_26.jpg stels_pilot_950_MD_26_copy.jpg

Более правильным подходом считается копирование не в построчном режиме а частями с фиксированным размером

with open('stels_pilot_950_MD_26.jpg', 'rb') as rf: with open('stels_pilot_950_MD_26_copy.jpg', 'wb') as wf: chunk_size = 4096 rf_chunk = rf.read(chunk_size) while len(rf_chunk) > 0: wf.write(rf_chunk) rf_chunk = rf.read(chunk_size)

РЕКЛАМА от Google. Может быть недоступна в вашем регионе.

Конец рекламы от Google. Если в блоке пусто считайте это рекламой моей телеги

Записать файл

Чтобы очистить файл от старого содержимого и записать в него новое используется опция w (write)

with open('log.txt', 'w') as f: f.write("some text")

Рассмотрим запись в файл в интерактивном режиме и без менеджера контекста

>>> f = open('sites.md', 'w') >>> f.write("topbicycle.ru")

13

>>> f.write("heihei.ru")

9

13 и 9 это число байт переданное в файл

>>> f.close() >>> exit() cat sites.md

topbicycle.ruheihei.ru

ls -l

-rw-r--r-- 1 andrei users 24 Jul 22 23:25 sites.md

Конечный размер файла будет зависеть от опецарионной системы.

В Windows и Linux разные переносы строк, поэтому когда Python применяет свой универсальный перенос строки количество байт может увеличится на 1 а может остаться прежним.

write() возвращает количество байт, переданных в файл, а не фактический размер записанных данных.

Если снова открыть файл и записать в него

>>> f = open('sites.md', 'w') >>> f.write("testsetup.ru") 12 >>> f.close()

Содержимое перезапишется.

testsetup.ru

Дописать в файл

Если нужно добавить новые данные к предыдущему содержимому без удаления - используется опция a (append)

with open('log.txt', 'a') as f: f.write("some text")

writelines(): Дописать в файл

Рассмотрим пример добавления данных в файл sites.md с помощью метода writelines()

www.topbicycle.ru www.heihei.ru www.eth1.ru

>>> f = open('sites.md', mode='at', encoding='utf-8') >>> f.writelines(['www.aviasales.ru\n', 'www.booking.com', 'www.tutu.ru\n', 'www.velodrive.ru', 'www.velosklad.ru']) >>> f.close() >>> exit()

cat sites.md

www.topbicycle.ru www.heihei.ru eth1.ruwww.aviasales.ru www.booking.comwww.tutu.ru www.velodrive.ruwww.velosklad.ru

Видно, что переносы строк появились только там, где их указали вручную.

Если нужно добавить данные не в конец файла, а в определённое место - изучите пример в статье «Продвинутые приёмы работы с файлами»

Похожие статьи
Работа с файлами в Python
Python
Продвинутые приёмы
glob: Работа с несколькими файлами
shutil: Работа с несколькими файлами
os
pathlib
Скачать файл по сети
.yaml.json
psutil: cистемные ресурсы
Обучение программированию на Python

РЕКЛАМА хостинга Beget, которым я пользуюсь более десяти лет

Изображение баннера

Конец рекламы хостинга Beget, который я всем рекомендую.

Поиск по сайту

Подпишитесь на Telegram канал @aofeed чтобы следить за выходом новых статей и обновлением старых

Перейти на канал

@aofeed

Задать вопрос в Телеграм-группе

@aofeedchat

Контакты и сотрудничество:
Рекомендую наш хостинг beget.ru
Пишите на info@urn.su если Вы:
1. Хотите написать статью для нашего сайта или перевести статью на свой родной язык.
2. Хотите разместить на сайте рекламу, подходящую по тематике.
3. Реклама на моём сайте имеет максимальный уровень цензуры. Если Вы увидели рекламный блок недопустимый для просмотра детьми школьного возраста, вызывающий шок или вводящий в заблуждение - пожалуйста свяжитесь с нами по электронной почте
4. Нашли на сайте ошибку, неточности, баг и т.д. ... .......
5. Статьи можно расшарить в соцсетях, нажав на иконку сети: