Как считать список из файла python
Перейти к содержимому

Как считать список из файла python

  • автор:

Чтение из файла в список

Необходимо точно такой же список открыть в python , чтобы работать с ним, например проходить его циклом, и так далее. Этот метод превращает все в строку.

with open('pairs.txt', 'r') as text: mylist = text.read() 

Этот метод делает из содержимого файла новый список, поглотив старый, с одним элементом внутри вместо 5. Как избавиться от общего списка?

with open('pairs.txt', 'r') as text: mylist = text.readlines() 

Отслеживать
76.7k 6 6 золотых знаков 54 54 серебряных знака 120 120 бронзовых знаков
задан 7 авг 2019 в 15:22
Кирилл Вишняков Кирилл Вишняков
483 1 1 золотой знак 8 8 серебряных знаков 18 18 бронзовых знаков

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Считываем файл и получаем текст

with open('pairs.txt', 'r') as f: text = f.read() print(text) # "[1,2,3,4,5]" 

Можно его распарсить как json через json.loads, т.к. синтаксически он верный:

import json items = json.loads(text) print(items) # [1, 2, 3, 4, 5] 

Или распарсить как тип python через ast.literal_eval:

import ast items = ast.literal_eval(text) print(items) # [1, 2, 3, 4, 5] 

Или парсим строку, составляя из нее список:

items = text[1:-1].split(',') print(items) # ['1', '2', '3', '4', '5'] items = list(map(int, text[1:-1].split(','))) print(items) # [1, 2, 3, 4, 5] items = [int(x) for x in text[1:-1].split(',')] print(items) # [1, 2, 3, 4, 5] 

Как считать список из файла python

Чтобы открыть текстовый файл на запись, необходимо применить режим w (перезапись) или a (дозапись). Затем для записи применяется метод write(str) , в который передается записываемая строка. Стоит отметить, что записывается именно строка, поэтому, если нужно записать числа, данные других типов, то их предварительно нужно конвертировать в строку.

Запишем некоторую информацию в файл «hello.txt»:

with open("hello.txt", "w") as file: file.write("hello world")

Если мы откроем папку, в которой находится текущий скрипт Python, то увидем там файл hello.txt. Этот файл можно открыть в любом текстовом редакторе и при желании изменить.

Теперь дозапишем в этот файл еще одну строку:

with open("hello.txt", "a") as file: file.write("\ngood bye, world")

Дозапись выглядит как добавление строку к последнему символу в файле, поэтому, если необходимо сделать запись с новой строки, то можно использовать эскейп-последовательность «\n». В итоге файл hello.txt будет иметь следующее содержимое:

hello world good bye, world

Еще один способ записи в файл представляет стандартный метод print() , который применяется для вывода данных на консоль:

with open("hello.txt", "a") as hello_file: print("Hello, world", file=hello_file)

Для вывода данных в файл в метод print в качестве второго параметра передается название файла через параметр file. А первый параметр представляет записываемую в файл строку.

Чтение файла

Для чтения файла он открывается с режимом r (Read), и затем мы можем считать его содержимое различными методами:

  • readline() : считывает одну строку из файла
  • read() : считывает все содержимое файла в одну строку
  • readlines() : считывает все строки файла в список

Например, считаем выше записанный файл построчно:

with open("hello.txt", "r") as file: for line in file: print(line, end="")

Несмотря на то, что мы явно не применяем метод readline() для чтения каждой строки, но в при переборе файла этот метод автоматически вызывается для получения каждой новой строки. Поэтому в цикле вручную нет смысла вызывать метод readline. И поскольку строки разделяются символом перевода строки «\n», то чтобы исключить излишнего переноса на другую строку в функцию print передается значение end=»» .

Теперь явным образом вызовем метод readline() для чтения отдельных строк:

with open("hello.txt", "r") as file: str1 = file.readline() print(str1, end="") str2 = file.readline() print(str2)
hello world good bye, world

Метод readline можно использовать для построчного считывания файла в цикле while:

with open("hello.txt", "r") as file: line = file.readline() while line: print(line, end="") line = file.readline()

Если файл небольшой, то его можно разом считать с помощью метода read() :

with open("hello.txt", "r") as file: content = file.read() print(content)

И также применим метод readlines() для считывания всего файла в список строк:

with open("hello.txt", "r") as file: contents = file.readlines() str1 = contents[0] str2 = contents[1] print(str1, end="") print(str2)

При чтении файла мы можем столкнуться с тем, что его кодировка не совпадает с ASCII. В этом случае мы явным образом можем указать кодировку с помощью параметра encoding :

filename = "hello.txt" with open(filename, encoding="utf8") as file: text = file.read()

Теперь напишем небольшой скрипт, в котором будет записывать введенный пользователем массив строк и считывать его обратно из файла на консоль:

# имя файла FILENAME = "messages.txt" # определяем пустой список messages = list() for i in range(4): message = input("Введите строку " + str(i+1) + ": ") messages.append(message + "\n") # запись списка в файл with open(FILENAME, "a") as file: for message in messages: file.write(message) # считываем сообщения из файла print("Считанные сообщения") with open(FILENAME, "r") as file: for message in file: print(message, end="")

Пример работы программы:

Введите строку 1: hello Введите строку 2: world peace Введите строку 3: great job Введите строку 4: Python Считанные сообщения hello world peace great job Python

Чтение данных из файла и запись в файл

В Python, чтобы создать файл, надо его открыть в режиме записи ( ‘w’ , ‘wb’ ) или дозаписи ( ‘a’ , ‘ab’ ).

f2 = open("text2.txt", 'w')

Функция open() возвращает файловый объект.

Без ‘b’ создается текстовый файл, представляющий собой поток символов. С ‘b’ — файл, содержащий поток байтов.

В Python также существует режим ‘x’ или ‘xb’ . В этом режиме проверяется, есть ли файл. Если файл с определенным именем уже существует, он не будет создан. В режиме ‘w’ файл создается заново, старый при этом теряется.

>>> f1 = open('text1.txt', 'w') >>> f2 = open('text1.txt', 'x') Traceback (most recent call last): File "", line 1, in FileExistsError: [Errno 17] File exists: 'text1.txt' >>> f3 = open('text1.txt', 'w')

Чтение данных из файла

Если в функцию open() не передается второй аргумент, файл расценивается как текстовый и открывается на чтение.

Попытка открыть на чтение несуществующий файл вызывает ошибку.

>>> f = open("text10.txt") Traceback (most recent call last): File "", line 1, in IOError: [Errno 2] No such file or directory: 'text10.txt'

Перехватить возникшее исключение можно с помощью конструкции try-except .

>>> try: . f = open("text10.txt") . except IOError: . print ("No file") . No file

Получить все данные из файла можно с помощью метода read() файлового объекта, предварительно открыв файл на чтение. При этом файловый объект изменяется и получить из него данные еще раз не получится.

>>> f = open("text.txt") >>> f >>> fd = f.read() >>> fd1 = f.read() >>> fd 'Hello\n\tOne\n Two\nThree Four\nШесть!\n' >>> fd1 ''

Если файл был открыт в текстовом режиме, то метод read() возвращает строку. В случае бинарного режима возвращается объект типа bytes .

>>> f = open('text.txt', 'rb') >>> content = f.read() >>> type(content) >>> content b'HelloHello' >>> content[0] 72 >>> chr(content[0]) 'H'

Методу read() может быть передан один аргумент, обозначающий количество символов (если файл был открыт как текстовый) или байт (если файл был открыт как бинарный) для чтения.

>>> f = open("text.txt") >>> fd = f.read(10) >>> fd1 = f.read(5) >>> fd 'Hello\n\tOne' >>> fd1 '\n T'

Метод readline() позволяет получать данные построчно.

>>> f = open("text.txt") >>> f.readline() 'Hello\n' >>> f.readline() '\tOne\n' >>> f.readline() ' Two\n'

Принимает аргумент — число байт или символов.

>>> f.readline(3) 'Thr' >>> f.readline(3) 'ee ' >>> f.readline(3) 'Fou' >>> f.readline(3) 'r\n' >>> f.readline(5) 'Шесть' >>> f.readline(5) '!\n'

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

>>> f = open('text.txt') >>> for line in f: . print(line, end='') . Hello! The second line. >>> f.close()

Метод readlines() считывает все строки и помещает их в список.

>>> f = open("text.txt") >>> fd = f.readlines() >>> fd ['Hello\n', '\tOne\n', ' Two\n', 'Three Four\n', 'Шесть!\n']

Может принимать количество символов, но дочитывает строку до конца.

>>> f = open("text.txt") >>> fd = f.readlines(3) >>> fd ['Hello\n'] >>> fd1 = f.readlines(6) >>> fd1 ['\tOne\n', ' Two\n']

Запись данных в файл

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

>>> ft = open('text1.txt', 'w') >>> fb = open('text2.txt', 'wb') >>> t = 'Привет Мир!' >>> b = b'Hello World!' >>> type(t), type(b) (, ) >>> ft.write(t) 11 >>> fb.write(b) 12 >>> ft.close() >>> fb.close() >>> >>> import os.path >>> os.path.getsize('text1.txt') 20 >>> os.path.getsize('text2.txt') 12 >>> open('text2.txt').read() 'Hello World!'

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

>>> a = [1, 2, 3, 4] >>> sa = str(a) >>> sa '[1, 2, 3, 4]' >>> f = open('mylist.txt', 'w') >>> f.write(sa) 12 >>> f.close() >>> >>> with open('mylist.txt') as f: . sa = f.read() . >>> sa '[1, 2, 3, 4]' >>> list(sa) # bad idea ['[', '1', ',', ' ', '2', ',', ' ', '3', ',', ' ', '4', ']'] >>> a = [int(i) for i in sa if i.isdigit()] >>> a [1, 2, 3, 4]

С помощью метода writelines() можно записать в файл итерируемую последовательность.

>>> a = [1,2,3,4,5,6,7,8,9,0] >>> f = open("text2.txt",'w') >>> f.writelines("%s\n" % i for i in a) >>> f.close() >>> open("text2.txt").read() '1\n2\n3\n4\n5\n6\n7\n8\n9\n0\n' >>> print(open("text2.txt").read()) 1 2 3 4 5 6 7 8 9 0

Смена позиции в файле

Метод tell() возвращает текущую позицию в файле. Позицию можно менять с помощью метода seek() .

>>> f = open('text.txt') >>> f.tell() 0 >>> f.readline() 'Hello!\n' >>> f.tell() 7 >>> f.seek(5) 5 >>> f.read(1) '!' >>> f.tell() 6 >>> f.read() '\nThe second line.\n' >>> f.read() '' >>> f.seek(0) 0 >>> f.read() 'Hello!\nThe second line.\n'

В случае бинарных файлов в метод seek() можно передавать второй аргумент, который указывает, с какого места выполняется смещение, указанное в первом аргументе: 0 (по умолчанию) — от начала файла, 1 — с текущей позиции, 2 — с конца.

>>> f = open('text.txt', 'rb') >>> f.read() b'Hello!\nThe second line.\n' >>> f.seek(-6, 2) 18 >>> f.read(4) b'line' >>> f.seek(0) 0 >>> f.read(5) b'Hello' >>> f.seek(2, 1) 7 >>> f.read(3) b'The'

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

В Python следует закрывать файл для высвобождения системных ресурсов. Делается это с помощью метода close() файлового объекта.

С помощью closed (не константа, а так называемый дескриптор, или описатель, данных) проверяют, закрыт файл или нет.

>>> f = open('text.txt') >>> f.closed False >>> f.close() >>> f.closed True

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

>>> with open('text.txt') as f: . print(f.read()) . HelloHello >>> f.closed True
>>> with open('text.txt') as fr, open('text2.txt', 'w') as fw: . fw.write(fr.read()) . 10 >>> fw.closed True 
>>> with ( . open('text.txt') as fr, . open('text2.txt', 'w') as fw, . ): . fw.write(fr.read()) . 10

Двоичные файлы

Пример копирования изображения:

>>> f1 = open('flag.png', 'rb') >>> f2 = open('flag2.png', 'wb') >>> f2.write(f1.read()) 446 >>> f1.close() >>> f2.close()

Модуль struct позволяет преобразовывать данные к бинарному виду и обратно.

>>> f = open('text3.txt', 'wb') >>> f.write('3') Traceback (most recent call last): File "", line 1, in TypeError: 'str' does not support the buffer interface >>> d = struct.pack('>i',3) >>> d b'\x00\x00\x00\x03' >>> f.write(d) 4 >>> f.close() >>> f = open('text3.txt') >>> d = f.read() >>> d '\x00\x00\x00\x03' >>> struct.unpack('>i',d) Traceback (most recent call last): File "", line 1, in TypeError: 'str' does not support the buffer interface >>> f = open('text3.txt', 'rb') >>> d = f.read() >>> d b'\x00\x00\x00\x03' >>> struct.unpack('>i',d) (3,)

Считываем числовые данные из файла на Python

В данной статье речь пойдет о простой на первой взгляд задаче — считывании числовых данных из текстовых файлов на Python. В сети можно найти десятки способов решения этой задачи, однако эти алгоритмы оказываются малоэффективными при работе с большим объемом данных. В данной статье будут разобраны самые популярные методики, а также произведено сравнение их скорости работы.

Введение

Когда я только начинал изучать Python, главным помощником в работе для меня, как наверное и для большинства программистов, был Stack Overflow. Я почерпнул оттуда много полезной информации, в том числе и о работе с файлами. Однако даже такая тривиальная задача, как оказалось, имеет несколько различных решений, отличающихся друг от друга простотой реализации и скоростью работы.

Большинство предложенных методов предполагают чтение файла построчно с дальнейшим разбиением на блоки и их преобразованием из строкового типа в числовой, поскольку Python в отличии от C/C++ работает с файлами как с массивом строк. Выполнить последовательное чтение данных в массив без преобразования типов, как это можно сделать в C/C++, стандартными средствами языка невозможно (насколько мне известно), и это существенно увеличивает время работы программы при обработке больших объемов данных.

Способы чтения данных из файла

Как уже было сказано выше, файлы в Python представляют собой массив строк, поэтому все найденные методы можно символически поделить на два типа в зависимости от используемого подхода:

  • построчное считывание с разбиением и преобразованием типов
  • использование библиотек, которые средствами других языков (например, C/C++) считывают файл и передают полученные данные интерпретатору Python

Ниже представлена подборка самых популярных методов чтения числовых данных на Python, отмеченных сообществом Stack Overflow как «best answer».

Способ 1 — построчное считывание с преобразованием

Самый популярный и простой вариант. Заключается в построчном чтении с разбиением полученной строки на блоки, которые затем преобразуются к необходимому типу данных (в данном случае float) и добавляются к заранее созданному списку.

data = [] with open("data.txt") as f: for line in f: data.append([float(x) for x in line.split()])

Способ 2 — преобразование при помощи map

Способ аналогичен предыдущему, за исключением того, что преобразованием данных из строкового формата в числовой занимается функция map.

file = open("data.txt", "r") data = [map(float, line.split("\t")) for line in file]

Способ 3 — с использованием регулярного выражения

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

import re file = open("data.txt") values = file.read().split("\n") data = [] for key in values: value = re.findall(r"[-+]?\d*\.\d+|\d+", key) if value != []: data.append(value)

Способ 4 — с использованием CSV Reader

Если данные записаны в виде матрицы с постоянными разделителями, то выполнить их чтение можно при помощи модуля CSV Reader, указав в качестве параметра значение разделителя.

import csv with open("data.txt") as f: data = [map(float, row) for row in csv.reader(f, delimiter='\t')]

Способ 5 — Numpy loadtxt

Библиотека Numpy предоставляет широкий набор модулей и функций для обработки числовых данных, в том числе и для чтения массивов из файлов. Одна из реализаций возможна с помощью функции loadtxt, результат работы которой будет записан в numpy.array.

import numpy as np data = np.loadtxt("data.txt", delimiter='\t', dtype=np.float)

Способ 6 — Numpy genfromtxt

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

import numpy as np data = np.genfromtxt("data.txt", delimiter='\t', dtype=np.float)

Способ 7 — Pandas read_csv

Pandas — мощная библиотека для обработки данных на Python. В данном примере рассматривается только чтение данных, но её возможности этим не ограничены. Метод read_csv предоставляет широкий набор входных параметров, а также показывается высокую скорость работы даже при работе с большими объемами данных.

import pandas as pd data = pd.read_csv("data.txt", sep="\t", header=None)

Методы тестирования скорости чтения

Для тестирования скорости чтения числовых данных были сгенерированы 7 тестовых файлов, содержащих 5 столбцов и 10, 100, 1 000, 10 000, 100 000, 1 000 000 и 10 000 000 строк случайных чисел формата float. Размер самого большого файла составил 742 Мб.

Для измерения времени работы программы использовалась функция time. Существует мнение, что измерять с её помощью время работы некорректно. Однако в данном случае меня интересовало работа с большими объемами данных, когда время работы программы составляло несколько десятков секунд. В таком случае отклонение в полсекунды вносило погрешность менее 1%.

Сравнение с компилируемыми языками программирования

Программы, созданные на компилируемых языках программирования, работают быстрее, чем их аналоги, написанные на интерпретируемых языках. Мне было интересно сравнить скорость чтения каждого метода с Fortran и C++ — самыми популярными языками в научном программировании, с которыми мне также приходится иметь дело в силу специфики моей работы.

Fortran

Несмотря на то, что Fortran считается устаревшим языком, он все еще очень популярен в научном программировании благодаря простоте написания кода, скорости обмена данных и обширном количестве библиотек, созданных за последние полвека.

Например, считать числовую матрицу из файла можно всего за 3 строчки кода при условии корректности входных данных.

real, dimension (5, 1000) :: data open (1, file='data.txt') read(1, *) data

C++

Дискуссии о том, что лучше: Fortran или C++ ведутся уже давно, даже среди авторов EasyCoding этот спор возникал несколько раз, поэтому мне было еще интересней протестировать чтение матриц на данном языке.

ifstream file(«data.txt»); int count = 100000; float** data = new float*[count]; for(int i = 0; i

Результаты тестирования

В ходе эксперимента были протестированы 7 программ на языке Python и по одной на Fortran и C++, код которых представлен выше. Запуск программ осуществлялся на компьютере с Intel Core i5 2.7 GHz и 8 Гб оперативной памяти.

Для запуска программ использовались следующие интерпретаторы и компиляторы:

  • Python 3.5.2
  • GNU Fortran (GCC) 6.1.0
  • g++ 4.2.1

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

Число строк Способ
1 2 3 4 5 6 7 Fortran C++
10 0.048 0.048 0.045 0.044 0.173 0.216 0.479 0.005 0.005
100 0.053 0.052 0.05 0.048 0.185 0.223 0.511 0.007 0.006
1 000 0.056 0.053 0.053 0.052 0.187 0.233 0.6 0.01 0.01
10 000 0.085 0.076 0.096 0.083 0.305 0.292 0.636 0.032 0.041
100 000 0.414 0.403 0.561 0.482 1.537 0.874 0.796 0.244 0.363
1 000 000 3.835 4.502 6.086 5.276 13.607 6.754 1.763 2.584 3.662
10 000 000 47.931 156.944 137.398 144.75 162.724 85.642 13.632 25.652 36.622

Итог

В ходе данного исследования были протестированы 7 самых популярных варианта чтения числовых матриц на языке Python, предложенными пользователями сайта Stack Overflow и отмеченными сообществом как «верный ответ». Как видно из таблицы с результатами, скорость работы программ не сильно отличается при использовании способов 1-4 на небольших объемах данных. Это связано с тем, что интерпретатор не тратит время на инициализацию сторонней библиотеки, как в методах 5-7.

Однако при увеличении объема входных данных лучше всех себя показал метод 7 с использованием библиотеки Pandas, который даже обогнал по скорости чтения данных языки C++ и Fortran.

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

10 commentaries to post

Наконец, нашел, что искал. Способ 6 — Numpy genfromtxt, который предоставляет более широкий набор входных параметров: указание различных типов данных для каждого из столбцов, передача ключей для создания ассоциативного массива и так далее.
Спасибо. Сэкономили время на поиск единственного, что нужно для моих вычислений по таблице «тексты-слова»…

ошибка в таблице ! 0.044 не меньше чем 0.005 а больше почти в 9 раз!
nightflash :
Нет ошибки. Автор сравнивал скорости Python решений.
С++, который обгонит всё перечисленное:
FILE* f = fopen(«data.txt», «rb») int count = 10000; float** data = new float*[count]; for(int i = 0; i < count; ++i)

Причем не особо кошерная реализация. Но соответствует предоставленному коду.
Кошерная реализация это:

fread(data, sizeof(float) * 5 * count, f);

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *