Стандартный поток ввода stdin
До этого момента для ввода данных с клавиатуры мы использовали функцию input()
. И этот способ хорошо работает, когда мы знаем, сколько строк с данными предстоит ввести, либо знаем, какая строка будет сигналом для остановки ввода данных. Но что делать, если количество входных строк мы не знаем, а строки для остановки ввода не предусмотрено? В таком случае следует использовать так называемый стандартный поток ввода. В него попадают все строки, которые вводит пользователь с клавиатуры. Программа может забирать строки из потока ввода одну за другой, а сами строки при этом удаляются из потока.
Чтобы подключить стандартный поток ввода stdin
в программу, необходимо его импортировать из модуля sys
:
from sys import stdin
Так как поток ввода stdin
по сути выступает итератором, по его элементам (введённым строкам) можно пройти в цикле. Использование потока ввода показано в следующей программе:
from sys import stdin
lines = []
for line in stdin:
lines.append(line)
print(lines)
Запустим программу и введём следующие данные:
Первая Вторая Третья
Теперь вводить данные мы можем практически бесконечно. Допустим, что после ввода третьей строчки нам нужно показать интерпретатору, что ввод данных завершён, можно выйти из цикла и продолжить работу программы. Для этого необходимо послать в поток ввода специальный символ — EOF
(end of file), нажав в консоли сочетание клавиш Ctrl+Z
в ОС Windows либо Ctrl+D
в ОС Linux и macOS. Когда в консоли Windows появится знак ^Z
, нужно нажать клавишу Enter
— ввод прекратится, а программа выдаст список введённых пользователем строк:
['Первая\n', 'Вторая\n', 'Третья\n']
Обратите внимание — каждая строка заканчивается символом перехода на новую строку. Если этот символ мешает дальнейшей обработке строк, его можно убрать, применив к каждой строке метод rstrip("\n")
перед добавлением в список:
from sys import stdin
lines = []
for line in stdin:
lines.append(line.rstrip("\n"))
print(lines)
Тогда результат работы программы для тех же введённых строк будет:
['Первая', 'Вторая', 'Третья']
Сохранить строки из потока ввода в список можно ещё проще — достаточно использовать метод readlines()
. Главное — не забудьте о том, что символ "\n" будет в конце каждой введённой строки:
from sys import stdin
lines = stdin.readlines()
print(lines)
Если необходимо сохранить все данные из потока ввода в одну строковую переменную, это можно сделать с помощью метода read()
:
from sys import stdin
text = stdin.read()
print([text])
Вывод программы для прежних введённых строк:
['Первая\nВторая\nТретья\n']
Мы поместили переменную text
в список для того, чтобы показать наличие в ней символов новой строки, а не просто сделать эти переходы при выводе. Как видим, переменная text
в примере будет содержать все введённые в поток ввода символы, включая "\n".
Файловый ввод-вывод
Итак, мы научились вводить данные в потоке с клавиатуры. Но программам часто требуется работать с данными из файлов.
Файл — это именованная область данных на носителе информации. Данные в файле представляются как последовательность байтов. Текстовые файлы можно прочитать как последовательность символов, если мы знаем их кодировку. В данном параграфе мы рассмотрим работу с текстовыми файлами в кодировке UTF-8
.
Для работы с файлами в Python есть встроенная функция open()
, которая имеет следующие основные аргументы:
file
— строка, содержащая путь до файла. Путь может быть абсолютным (от буквы диска в Windows или от корневой папки в Linux) или относительным (от папки, в которой находится запущенная программа);mode
— режим доступа к файлу. Рассмотрим следующие режимы:"r"
— режим чтения текстового файла; является режимом по умолчанию;"w"
— режим записи нового текстового файла; файл всегда создаётся заново;"a"
— режим записи текстового файла; если файла нет, то он создаётся, иначе данные добавляются в конец существующего файла;"+"
— добавляется в конец обозначения предыдущих режимов и позволяет работать с файлом одновременно в режиме чтения и записи.
encoding
— строка, содержащая обозначение кодировки текстового файла (например,"UTF-8"
).
Прочитаем текстовый файл в кодировке UTF-8
. Вы можете создать файл самостоятельно в «Блокноте», но не забудьте при сохранении указать кодировку UTF-8
:
file_in = open("input_1.txt", encoding="UTF-8")
Обратите внимание на то, что кодировка UTF-8
является стандартной для ОС Linux и macOS. А вот для Windows её нужно обязательно указывать в именованном аргументе encoding
, так как кодировкой по умолчанию для ОС Windows является cp-1251
. Также следует учитывать, что для поддержки кросс-платформенности программ кодировку всё равно лучше указывать в явном виде.
Функция open()
возвращает файловый объект, у которого есть методы для работы с файлом. Для построчного чтения файла можно пройти по нему в цикле:
file_in = open("input_1.txt", encoding="UTF-8")
for line in file_in:
print(line)
file_in.close()
Вывод программы для файла из примера:
Привет! Это пример текстового файла. А это — последняя строка, которая заканчивается переходом на новую.
Мы видим, что между выводом строк из файла добавились пустые строчки. Это произошло потому, что в конце каждой считанной строки добавляется символ \n
, а функция print()
также добавляет \n
. Эта ситуация похожа на работу с stdin
, и убрать \n
можно так же — вызовом метода rstrip("\n")
.
Обратите внимание: после работы с файлом его необходимо закрыть с помощью метода close()
. Если этого не сделать, файл будет недоступен другим программам, так что не забывайте его закрывать, если он больше не используется. А чтобы не забыть, можно воспользоваться менеджером контекста with
, который закроет файл даже в случае возникновения ошибок в процессе работы. Блок менеджера контекста имеет отступ в четыре пробела:
with open("input_1.txt", encoding="UTF-8") as file_in:
for line in file_in:
print(line.rstrip("\n"))
Вывод программы:
Привет! Это пример текстового файла. А это — последняя строка, которая должна закончиться переходом на новую.
Следует помнить о том, что устройство хранения данных является самым медленным в компьютере, так что частые операции с файлами будут снижать скорость работы вашей программы. Поэтому, если позволяют ресурсы компьютера (объём оперативной памяти), файл лучше прочитать сразу целиком, работать с ним в оперативной памяти и записывать в файл полностью полученный результат.
Для получения полного списка строк текстового файла используется метод readlines()
:
with open("input_1.txt", encoding="UTF-8") as file_in:
lines = file_in.readlines()
print(lines)
Вывод программы:
['Привет!\n', 'Это пример текстового файла.\n', 'А это — последняя строка, которая должна закончиться переходом на новую.\n']
Для чтения символов файла в строковую переменную используется метод read()
. Прочитаем 10 символов файла:
with open("input_1.txt", encoding="UTF-8") as file_in:
symbols = file_in.read(10)
print([symbols])
Вывод программы:
['Привет!\nЭт']
Если в методе read()
не указать количество считываемых символов, то прочитается весь файл.
Для записи в файл его необходимо сначала открыть в режиме записи (выше была информация о режимах доступа). Для записи данных из строковой переменной используется метод write()
:
with open("output_1.txt", "w", encoding="UTF-8") as file_out:
n = file_out.write("Это первая строка\nА вот и вторая\nИ третья — последняя\n")
print(n)
Метод write()
возвращает количество записанных в файл символов.
Для записи строк из списка в файл используется метод writelines()
. Этот метод записывает строки в файл по очереди, без разделителя. Пример его использования:
lines = ["Это первая строка\n", "А вот и вторая\n", "И третья — последняя\n"]
with open("output_2.txt", "w", encoding="UTF-8") as file_out:
file_out.writelines(lines)
Содержимое выходного файла:
Это первая строка А вот и вторая И третья — последняя
Функция print()
может быть использована для вывода данных в файл. Для этого нужно передать ей в аргумент file
файловый объект:
with open("output_3.txt", "w", encoding="UTF-8") as file_out:
print("Вывод в файл с помощью функции print()", file=file_out)
Содержимое выходного файла:
Вывод в файл с помощью функции print()
JSON
Существуют такие форматы текстовых файлов, которые могут хранить в себе информацию, структурированную по некоторым правилам. Один из таких форматов — JSON
(JavaScript Object Notation). Как видно из названия, он был создан для языка JavaScript, но в настоящее время является независимым от него и может использоваться практически с любым языком программирования.
Для значений в JSON можно использовать:
- строки — для обозначения строки используются строго двойные кавычки;
- числа — целые и вещественные;
- логические значения true и false — записываются, в отличие от Python, со строчной буквы.
Для хранения неупорядоченных наборов данных в JSON можно использовать записи, то есть пары «ключ: значение» (аналог словаря в Python). Также можно хранить упорядоченные последовательности значений (аналог списка в Python).
Посмотрим, что представляет собой JSON-файл на примере. Предположим, что нужно хранить структурированную информацию о студентах следующего вида: фамилия (last_name), имя (first_name), отчество (patronymic), дата рождения (date_of_birth), номер группы (group_number), список номеров телефонов (phones_numbers).
Тогда список с информацией о студентах можно представить в следующем виде:
[ { "last_name": "Иванов", "first_name": "Иван", "patronymic": "Иванович", "date_of_birth": "01.01.2001", "group_number": 1, "phone_numbers": [ "+7 111 111 1111", "+7 111 111 1112" ] }, { "last_name": "Петров", "first_name": "Пётр", "patronymic": "Петрович", "date_of_birth": "10.10.2001", "group_number": 1, "phone_numbers": [ "+7 111 111 1113", "+7 111 111 1114" ] } ]
Мы видим, что в JSON-файле находится список из двух записей, очень похожих на словарь Python.
Для более удобной работы с JSON-файлами существует стандартный модуль json
. Он позволяет преобразовать данные из JSON-файла в вашей программе в стандартные типы данных Python, а также способен выполнить обратную операцию для записи данных в JSON-файл.
Для чтения JSON-файлов используется метод load()
, считывающий весь JSON-файл целиком и возвращающий объект стандартного типа данных Python.
Прочитаем JSON-файл с данными из примера:
import json
with open("data.json", encoding="UTF-8") as file_in:
records = json.load(file_in)
print(records)
Вывод программы:
[{'date_of_birth': '01.01.2001', 'first_name': 'Иван', 'group_number': 1, 'last_name': 'Иванов', 'patronymic': 'Иванович', 'phone_numbers': ['+7 111 111 1111', '+7 111 111 1112']}, {'date_of_birth': '10.10.2001', 'first_name': 'Пётр', 'group_number': 1, 'last_name': 'Петров', 'patronymic': 'Петрович', 'phone_numbers': ['+7 111 111 1113', '+7 111 111 1114']}]
Из примера видно, что JSON-файл был преобразован в список словарей, а каждый словарь — это запись с информацией о студенте. Для обработки стандартных объектов мы можем применить известные операции, функции и методы. Для записи изменённых данных в JSON-файл используется метод dump()
. Рассмотрим некоторые важные его аргументы:
- ensure_ascii. Имеет значение по умолчанию True, при котором все не-ASCII-символы при выводе в файл представляют собой юникод-последовательности вида
\uXXXX
(коды символов в таблице кодировки). Если аргумент имеет значение False, такие символы будут записаны в виде символов, а не их кодов. В примере используются русские символы, поэтому необходимо передать в аргумент значение False. - indent. Задаёт вид отступа для удобства чтения данных человеком. По умолчанию аргумент имеет значение None, а данные записываются в файл одной строкой. Если задать строку вместо None, то эта строка будет использоваться в качестве отступа. Если задать число больше 0, то отступ будет состоять из такого же количества пробелов.
- sort_keys. Позволяет отсортировать ключи словаря с данными. По умолчанию имеет значение False. Для сортировки ключей необходимо передать в аргумент значение True.
Изменим номер группы у второго студента и сохраним данные в исходный файл:
import json
with open("data.json", encoding="UTF-8") as file_in:
records = json.load(file_in)
records[1]["group_number"] = 2
with open("data.json", "w", encoding="UTF-8") as file_out:
json.dump(records, file_out, ensure_ascii=False, indent=2)
Содержимое файла data.json после работы программы:
[ { "last_name": "Иванов", "first_name": "Иван", "patronymic": "Иванович", "date_of_birth": "01.01.2001", "group_number": 1, "phone_numbers": [ "+7 111 111 1111", "+7 111 111 1112" ] }, { "last_name": "Петров", "first_name": "Пётр", "patronymic": "Петрович", "date_of_birth": "10.10.2001", "group_number": 2, "phone_numbers": [ "+7 111 111 1113", "+7 111 111 1114" ] } ]
Итак, модуль json
позволяет работать с данными в JSON-файле как с объектами языка Python. Важно помнить, что в качестве ключа в записях JSON может использоваться только строка. При записи в JSON-файл словаря Python, в котором ключи могут быть любым неизменяемым типом данных, производится автоматическое преобразование в правильный тип данных. В примере словарь содержит целочисленные ключи, а в JSON-файле эти ключи преобразованы в строки:
import json
records = {1: "First",
2: "Second",
3: "Third"}
with open("output.json", "w", encoding="UTF-8") as file_out:
json.dump(records, file_out, ensure_ascii=False, indent=2)
Содержимое файла output.json после работы программы:
{ "1": "First", "2": "Second", "3": "Third" }