Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

31 KiB

Отчёт по теме 6: Ввод-вывод данных и операции с файлами

Филиппов Даниил Юрьевич, А-01-23

1. Запуск интерактивной оболочки IDLE

>>> import os
>>> os.chdir('C:\\Users\\danii\\Desktop\\FilippovDY\\python-labs\\TEMA6')

2. Вывод данных на экран дисплея

2.1 Вывод в командной строке

Упоминание имя файла в строке:

>>> stroka='Автоматизированная система управления'
>>> stroka
'Автоматизированная система управления'

Этот способ называется «эхо-выводом». Он пригоден при работе в командной строке, однако в пользовательских функциях этот способ применять нельзя.

2.2 Вывод с использованием функции print

Этот способ можно применять и в командной строке, и в функциях. По умолчанию вывод будет осуществляться на экран, но пункт назначения выводимых данных можно переопределить.

>>> fff=234.5;gg='Значение температуры = '
>>> print(gg, fff)   #Можно вывести несколько объектов за одно обращение к функции
Значение температуры =  234.5

По умолчанию выводимые объекты разделяются одним пробелом. Если нужен другой разделитель его можно указать в отдельном аргументе sep:

>>> print(gg, fff, sep='/')
Значение температуры = /234.5

После вывода автоматически осуществляется переход на другую строку. Если курсор надо оставить в той же строке, то следует использовать еще один аргумент:

>>> print(gg, fff,sep='/',end='***'); print('____')
Значение температуры = /234.5***____

После end= надо указать какими символами должна закончиться выводимая строка или указать пустую строку. Если в какой-то момент требуется просто перейти на новую строку, можно использовать следующее обращение к функции:

>>> print()

Оператор вывода может располагаться на нескольких строках с использованием тройных кавычек:

>>> print(""" Здесь может выводиться
... большой текст,
... занимающий несколько строк""")
... 
 Здесь может выводиться
большой текст,
занимающий несколько строк
>>> print("Здесь может выводиться",
...      "большой текст,",
...      "занимающий несколько строк")
Здесь может выводиться большой текст, занимающий несколько строк

Разница в двух случаях состоит в том, что в первом случае тройные кавычки воспроизводят текст ровно так, как он был введен. Во втором случае три выводимых объекта-строки перечисленны через запятую и выведены как три объекта, разделённые пробелом.

2.3 Вывод с использованием метода write объекта sys.stdout

Объект stdout представляет собой поток стандартного вывода – объект, в который программы выводят символьное представление данных. Обычно это – экран дисплея. Объект находится в модуле sys, который надо импортировать:

>>> sys.stdout.write('Функция write')
Функция write13
>>> sys.stdout.write('Функция write\n') 
Функция write
14

Этот метод после вывода строки не осуществляет переход на новую строку. Если это требуется, то следует в конце строки добавить один или несколько символов “\n”. Так же эта функция возвращает число - количество введенных символов, причем \n считается за один символ, а не за два.

3. Ввод данных с клавиатуры

Для ввода данных используем стандартную функцию input:

>>> psw=input('Введите пароль:')
Введите пароль:12345
>>> psw
'12345'
>>> type(psw)
<class 'str'>

input() всегда возвращает строку, даже если ввести числа или функцию. Если нужна не строка, то input надо поместить внутрь функции, изменяющей тип данных. Например, int(input()).

Пример 1: Ввод с контролем значения. Пусть вводится число, которое должно находиться в интервале значений от 17.5 до 23.8.

>>> while True:
... 	znach=float(input('Задайте коэф.усиления = '))
... 	if znach<17.5 or znach>23.8:
... 		print('Ошибка!')
... 	else:
... 		break
... 
Задайте коэф.усиления = 15.4
Ошибка!
Задайте коэф.усиления = 23.8
>>> znach
23.8

Пример 2: Ввод и обработка выражения, подлежащего расчету.

>>> import math
>>> print(eval(input('введите выражение для расчета = ')))
введите выражение для расчета = math.log10(23/(1+math.exp(-3.24)))
1.34504378689765

Введенная строка преобразуется в исполнительные инструкции с помощью eval(), далее они выполняются и результат выводится на экран. Строка имеет тип, соответствующий результату вычислений. В данном случае - float.

4. Ввод-вывод при работе с файлами

4.1 Функции для работы с путём к файлу

Эти функции собраны в модуле os. Поэтому при работе с файлами надо импортировать этот модуль. Текущий рабочий каталог можно узнать с помощью функции os.getcwd:

>>> import os
>>> os.getcwd()
'C:\\Users\\danii\\Desktop\\FilippovDY\\python-labs\\TEMA6'
>>> Filippov = os.getcwd() # Сохранение пути в переменной
>>> print(Filippov) # При данном выводе используются одинарный "\"
C:\Users\danii\Desktop\FilippovDY\python-labs\TEMA6

В начале сеанса работы со средой Python в качестве рабочего каталога по умолчанию устанавливается путь к каталогу, в котором был установлен Python, например, 'C:\Python34'. При запуске из текстового редактора IDLE программы, находящейся в некотором файле, за рабочий каталог принимается тот, в котором расположен файл с программой. Изменить расположение рабочего каталога можно с помощью функции os.chdir, аргументом которой будет символьная строка с указанием пути к каталогу, назначаемому в качестве рабочего.

Функция создания каталога - mkdir. Параметры функции: path - путь к создаваемой директории; mode - права доступа.

>>> help(os.mkdir)
Help on built-in function mkdir in module nt:

mkdir(path, mode=511, *, dir_fd=None)
    Create a directory.

    If dir_fd is not None, it should be a file descriptor open to a directory,
      and path should be relative; path will then be relative to that directory.
    dir_fd may not be implemented on your platform.
      If it is unavailable, using it will raise a NotImplementedError.

    The mode argument is ignored on Windows. Where it is used, the current umask
    value is first masked out.

>>> os.mkdir("новая_папка") # Создание директории в текущей папке

Удаление каталога - rmdir:

>>> os.rmdir('C:\\Users\\danii\\Desktop\\FilippovDY\\python-labs\\TEMA6\\новая_папка')

Мы не можем удалить каталог, в котором находимся. Чтобы исправить ситуацию нам нужно подняться на уровень выше в директории и тогда произвести удаление.

Функция показа списка всех файлов и папок, вложенных в текущую - listdir:

>>> os.listdir()
['.gitkeep', 'report.md']

Функция проверки существования каталога - isdir. Функция isdir() модуля os.path возвращает True если путь path существует и является каталогом, в противном случае False.

>>> os.path.isdir("C:/Users/danii/Desktop/FilippovDY/python-labs/TEMA6")
True
>>> os.path.isdir("report.md") # Данный файл существует, но не является каталогом
False

Функция преобразования пути, переданного в качестве аргумента, в абсолютный путь - os.path.abspath(). Абсолютный путь — это полный путь к файлу или каталогу, начиная от корневого каталога системы, а не относительный путь (который зависит от текущего рабочего каталога).

>>> os.path.abspath("report.md") # Файл существует
'C:\\Users\\danii\\Desktop\\FilippovDY\\python-labs\\TEMA6\\report.md'
>>> os.path.abspath("test.md") # Такого файла нет
'C:\\Users\\danii\\Desktop\\FilippovDY\\python-labs\\TEMA6\\test.md'

Если передать в os.path.abspath() несуществующий файл или каталог, функция не проверяет наличие этого файла в файловой системе, она просто преобразует путь в абсолютный.

Функции отделения из абсолютного пути только каталога/только имени файла - dirname/basename:

>>> os.path.abspath("report.md")
>>> drkt=os.path.dirname(os.path.abspath("report.md"))
>>> drkt
'C:\\Users\\danii\\Desktop\\FilippovDY\\python-labs\\TEMA6'
>>> bsnm = os.path.basename(os.path.abspath("report.md"))
>>> bsnm
'report.md'

Функция разделения на кортеж из пути и из имени файла - split:

>>> os.path.split(os.path.abspath("report.md"))
('C:\\Users\\danii\\Desktop\\FilippovDY\\python-labs\\TEMA6', 'report.md')
>>> type(os.path.split(os.path.abspath("report.md")))
<class 'tuple'>

Функция проверки существования пути, заданного в символьной строке - exists:

>>> os.path.exists("C:/Users/danii/Desktop/FilippovDY/python-labs/TEMA6") # Такой каталог есть
True
>>> os.path.exists("C:/Users/danii/Desktop/FilippovDY/python-labs/TEMA12") # Такого каталога нет
False

Функция проверки существования файла - isfile:

>>> os.path.isfile("C:/Users/danii/Desktop/FilippovDY/python-labs/TEMA6/report.md") # Такой файл есть
True
>>> os.path.isfile("C:/Users/danii/Desktop/FilippovDY/python-labs/TEMA6/figure_1.png") # Такого файла нет
False
>>> os.path.isfile("C:/Users/danii/Desktop/FilippovDY/python-labs/TEMA6") # Выбран только каталог
False

4.2 Общая схема работы с файлом

Для обмена данными с файлом необходимо выполнить следующие операции: Открытие файла с указанием его имени и цели (чтение, запись, добавление данных); Выполнение одной или нескольких операций обмена данными с файлом; Закрытие файла.

4.3 Открытие файла для записи или чтения данных - функция open.

При открытии файла необходимо указать имя файлы (с путем, если он не в рабочем каталоге) и цель работы с ним. Для открытия используется функция open.

fp=open(file=drkt+'\\zapis1.txt',mode='w')
>>> type(fp)                                                         
<class '_io.TextIOWrapper'>
>>> fp                                                         
<_io.TextIOWrapper name='C:\\Users\\danii\\Desktop\\FilippovDY\\python-labs\\TEMA6\\zapis1.txt' mode='w' encoding='cp1251'>

fp – это файловый объект, который в других языках программирования обычно называют файловой переменной. Он сохраняет ссылку на открываемый файл и позволяет в дальнейшем ссылаться на файл, не указывая путь и имя открытого файла. В аргументе функции с именем file указывается путь и имя открываемого файла, а в аргументе с именем mode – предполагаемая цель его использования (w=write – для записи).

Аргументы функции с их именами могут располагаться в любом порядке. Если имя файла располагается на месте первого аргумента, а цель использования – на втором, то имена аргументов можно не указывать:

>>> fp=open(drkt+'\\zapis1.txt','w')

Если путь в переменной drkt совпадает с рабочим каталогом, то его можно опустить, оставив только имя открываемого файла:

>>> fp=open('zapis1.txt','w')
>>> fp                                                           
<_io.TextIOWrapper name='zapis1.txt' mode='w' encoding='cp1251'>

Отобразим список атрибутов объекта fp:

>>> dir(fp)                                                          
['_CHUNK_SIZE', '__class__', '__del__', '__delattr__', '__dict__', '__dir__', '__doc__', '__enter__', '__eq__', '__exit__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__module__', '__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']

Файл по такой инструкции открывается только для записи. Если требуются другие операции с открываемым файлом, то для второго аргумента «mode=…» могут быть заданы следующие значения: w – запись с созданием нового файла или перезапись существующего файла, w+ - чтение и запись/перезапись файла, r – только чтение (это значение - по умолчанию), r+ - чтение и/или запись в существующий файл, a – запись в конец существующего файла или, если его нет, запись с созданием файла, a+ - то же, что и в «a», но с возможностью чтения из файла.

Создаваемые и читаемые файлы могут быть бинарными или символьными. При открытии бинарного файла к указанным выше буквам в аргументе-цели надо добавить символ «b»:

>>> fp1=open(drkt+'\\zapis2.bin',mode='wb+')                                                          
>>> fp1                                                           
<_io.BufferedRandom name='C:\\Users\\danii\\Desktop\\FilippovDY\\python-labs\\TEMA6\\zapis2.bin'>

В бинарный файл можно без преобразования записывать объекты любого типа. Если файл – символьный, то его тип обозначается «t», но это – значение по умолчанию и его можно не указывать. В символьный файл можно записывать только объекты типа str. Объекты других типов надо перед записью преобразовать к этому типу.

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

Сразу после завершения работы с файлом его следует закрыть для обеспечения сохранности его содержимого. Это делается с помощью метода close:

>>> fp.close()

4.5 Запись информации в файл с помощью метода write.

Метод write относится к объекту – файловой переменной. Рассмотрим его применение на следующем примере: создайте список с элементами-числами от 1 до 12 и запишите их в файл по 4 числа на строке:

>>> sps=list(range(1,13))
>>> fp2=open('zapis3.txt','w')
>>> fp2.write(str(sps[:4])+'\n')
13
>>> fp2.write(str(sps[4:8])+'\n')
13
>>> 
>>> fp2.write(str(sps[8:])+'\n')
16
>>> fp2.close()

Откроем файл zapis3.txt и посмотрим его содержимое: [1, 2, 3, 4] [5, 6, 7, 8] [9, 10, 11, 12] В файл записались преобразованные в строки срезы списка. Метод выполняет действия по записи данных в файл, но возвращает количество записанных символов.

Следующий пример:

>>> sps3=[['Иванов И.',1],['Петров П.',2],['Сидоров С.',3]]
>>> fp3=open('zapis4.txt','w')
>>> for i in range(len(sps3)):
... 	stroka4=sps3[i][0]+' '+str(sps3[i][1])
... 	fp3.write(stroka4)
... 	
11
11
12
>>> fp3.close()

Содержание файла zapis4.txt: Иванов И. 1Петров П. 2Сидоров С. 3

Видно, что строки склеились там, где это не надо. Попробуем сделать по-другому:

>>> gh=open('zapis5.txt','w')
>>> for r in sps3:
... 		gh.write(r[0]+' '+str(r[1])+'\n')
... 
... 		
12
12
13
>>> gh.close()

Содержание файла zapis5.txt: Иванов И. 1 Петров П. 2 Сидоров С. 3 Мы добавили перенос строки после каждой итерации и пробел в нужном для нас месте.

4.6 Первый способ чтения информации из текстового файла.

Информация в текстовом файле размещена последовательно, по строкам, с завершением каждой строки символом \n (конец строки). При чтении из файла из него извлекается часть информации, начиная с некоторого символа. Обычно, для удобства, считают, что перед этим символом стоит невидимый маркер (указатель), который при открытии файла устанавливается перед первым символом. После чтения части информации маркер перемещается и ставится перед символом, следующим за прочитанной частью информации. Прочитаем информацию из файла zapis3.txt:

>>> sps1=[]
>>> fp=open('zapis3.txt') # Файл открыт в режиме чтения (по умолчанию)
>>> for stroka in fp:
... 	stroka=stroka.rstrip('\n')
... 	stroka=stroka.replace('[','')
... 	stroka=stroka.replace(']','')
... 	sps1=sps1+stroka.split(',')
... 
>>> fp.close()
>>> sps1
['1', ' 2', ' 3', ' 4', '5', ' 6', ' 7', ' 8', '9', ' 10', ' 11', ' 12']
>>> sps
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

Здесь, перед занесением строки в список с помощью метода rstrip, из неё удаляется символ конца строки (если не задавать аргументов, он удалит любые пробелы (пробел, табуляция, символы новой строки и т.п.) с конца строки.), а с помощью метода replace – скобки. Видно, что полученный список отличается от исходного sps типом данных, а также не убраны некоторые пробелы. Исправим это:

>>> sps2 = [int(i.strip()) for i in sps1]
>>> sps2
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

Это list comprehension, который у кажлого элемента sps1 убирает лишние пробелы с обеих сторон (в этом отличие rstrip от strip). Затем полученная строка конвертируется в число.

4.7 Чтение информации из файла с помощью метода read

Метод read, как и write, относится к объекту – файловой переменной. В качестве аргумента этого метода может задаваться целое число – количество символов или, если открыт бинарный файл, - количество байт, которое должно быть прочитано, соответственно, из текстового или бинарного файла, начиная с текущего положения маркера. Если указанное число превышает количество оставшихся символов (байт) в файле, то считываются все оставшиеся символы (байты). Если это число не указано, то считываются вся информация от маркера до конца файла. Метод возвращает строку с символами или совокупность байт, прочитанных из файла.

>>> fp=open('zapis3.txt')
>>> stroka1=fp.read(12) # Чтение первых 12 файлов, курсор остановится на 13-ом (/n)
>>> stroka2=fp.read() # Чтение всех оставшихся файлов 
>>> fp.close()
>>> stroka1
'[1, 2, 3, 4]'
>>> stroka2
'\n[5, 6, 7, 8]\n[9, 10, 11, 12]\n'

4.8 Чтение информации с помощью методов readline и readlines

Метод readline() считывает одну строку из файла за один вызов. Он читает символы до тех пор, пока не встретит символ новой строки (\n) или конец файла (EOF). Метод readlines() считывает все строки файла и возвращает их в виде списка, где каждая строка — это отдельный элемент списка. Каждая строка в списке будет содержать символ новой строки \n, если он есть в файле.

>>> file = open("zapis5.txt")
>>> file.readline()
'Иванов И. 1\n'
>>> file.close()
>>> file = open("zapis5.txt")
>>> file.readlines()
['Иванов И. 1\n', 'Петров П. 2\n', 'Сидоров С. 3\n']
>>> file.close()

4.9 Ввод-вывод объектов с использованием функций из модуля pickle

В модуле pickle содержатся функции для работы с бинарными файлами, в которые могут последовательно записываться или считываться целиком один или несколько объектов из оперативной памяти.

>>> import pickle
>>> mnoz1={'pen','book','pen','iPhone','table','book'}
>>> fp=open('zapis6.mnz','wb') # Бинарный файл – на запись
>>> pickle.dump(mnoz1,fp) # dump – метод записи объекта в файл
>>> fp.close()

Содержание файла zapis6.mnz: 耄锣 鐨谆楐桯湥钌Ͱ敮钌Ѣ潯殔谅瑡扬斔逮

Так происходит, потому что байты в этом файле не предназначены для текстового представления. Они могут содержать символы, которые не могут быть корректно интерпретированы в рамках текстовой кодировки.

Прочитаем данные из файла в объект mnoz2:

>>> fp=open('zapis6.mnz','rb')
>>> mnoz2=pickle.load(fp)  #load – метод чтения объекта из бинарного файла
>>> fp.close()
>>> mnoz2
{'iPhone', 'pen', 'book', 'table'}
>>> mnoz1
{'iPhone', 'pen', 'book', 'table'}
>>> mnoz1==mnoz2
True

mnoz1 не совпадает с изначально заданным mnoz1, потому что данный тип объекта исключает повторяющиеся элементы.

Теперь с использованием тех же функций запишем в файл, а затем прочитаем два объекта разных типов. При считывании объекты извлекаются из файла в той же последовательности, в которой они в него записывались:

>>> fp=open('zapis7.2ob','wb')
>>> pickle.dump(mnoz1,fp)
>>> pickle.dump(sps3,fp)
>>> fp.close()
>>> fp=open('zapis7.2ob','rb')
>>> obj1=pickle.load(fp)  #Первое обращение к load читает первый объект
>>> obj2=pickle.load(fp)  #Второе – читает второй
>>> fp.close()
>>> obj1
{'iPhone', 'pen', 'book', 'table'}
>>> obj2
[['Иванов И.', 1], ['Петров П.', 2], ['Сидоров С.', 3]]

5. Перенаправление потоков ввода и вывода данных

Поток - это абстракция, которая позволяет регулировать источники ввода информации и то, куда её выводить. По умолчанию их три: sys.stdin — поток ввода sys.stdout — поток вывода sys.stderr — поток ошибок

>>> import sys # Модуль для работы с потоками
>>> vr_out=sys.stdout  #Запоминаем текущий поток вывода
>>> fc=open('Stroka.txt','w') #Откроем файл вывода
>>> sys.stdout=fc #Перенацеливаем стандартный поток вывода на файл
>>> print('запись строки в файл') #Вывод теперь будет не на экран, а в файл
>>> sys.stdout=vr_out  #Восстановление текущего потока
>>> print('запись строки на экран') #Убеждаемся, что вывод на экран восстановился
запись строки на экран
>>> fc.close()

В результате создан файл Stroka.txt в текущем каталоге с содержанием: 'запись строки в файл'

Точно также можно перенаправить поток ввода – sys.stdin – вместо клавиатуры – из файла:

>>> tmp_in = sys.stdin #Запоминаем текущий поток ввода
>>> fd = open("Stroka.txt", "r") #Открываем файл для ввода (чтения)
>>> sys.stdin = fd #Перенацеливаем ввод на файл вместо клавиатуры
>>> sys.stdin
<_io.TextIOWrapper name='Stroka.txt' mode='r' encoding='cp1251'>
>>> while True:
... 	try:
... 		line = input () #Считываем из файла строку
... 		print(line)  # Отображаем считанное
... 	except EOFError:
... 		break
... 
запись строки в файл
>>> fd.close()
>>> sys.stdin=tmp_in # Возвращение стандартного назначения для потока ввода

Конструкция try-except предназначена для отладки исключений: если возвращается ошибка, можно ее перехватить и указать, что делать в таком случае.

6. Завершение сеанса работы с IDLE