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

от admin

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

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

Введение

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Способ 5 — Numpy loadtxt

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

Способ 6 — Numpy genfromtxt

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

Способ 7 — Pandas read_csv

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

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

Для тестирования скорости чтения числовых данных были сгенерированы 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 строчки кода при условии корректности входных данных.

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

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

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

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

GNU Fortran (GCC) 6.1.0

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

Число строк Способ
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 раз!

Нет ошибки. Автор сравнивал скорости Python решений.

С++, который обгонит всё перечисленное:

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

Спасибо за приведенное полезное сравнение. Не хватает сравнения скорости записи (в рам для точности)

К способу 6:
ModuleNotFoundError: No module named ‘numpy’
Ругается на import в начале

Необходимо установить соответствующую библиотеку numpy либо из репозиториев, либо посредством pip.

2 способ выдает:
[/, /, /]
при числах в файле:
1 2 3
4 5 6
7 8 9
Что не так?

Проверьте версию интерпретатора Python. В 3.7 работает нормально.

На С++ вы читали потоками, это медленно. Надо было попробовать функциями ввода вывода,fopen, fclose, fread должно быть быстрее. В С++ тоже несколько способов. Могло получиться сопоставимо с лучшим результатом.

Name already in use

py_training_ru / lecture_08.md

  • Go to file T
  • Go to line L
  • Copy path
  • Copy permalink
  • Open with Desktop
  • View raw
  • Copy raw contents Copy raw contents

Copy raw contents

Copy raw contents

Лекция 8. Ввод-вывод в файлы. Конструкция with

Значки, используемые в тексте

  • �� — отмечает, что высказывание не совсем верно, но будет уточнено позднее.
  • ⭐ — выделяет определение нового понятия.
  • ❗ — привлекает внимание к высказыванию.
  • ☝️ — указывает на небольшое отступление от темы или уточнение.
  • �� — индикатор традиций и договорённостей.
  • ⚠️ — требуется осторожность: возможно, сложное высказывание.

Повторение терминов из седьмой лекции

  • Конструкция try-except-else — синтаскическая конструкция (сложное утверждение), предназначенная для обработки исключений из блока try в блоках except и выполнения блока else в случае отсутствия ошибок.
  • Утверждение raise — утверждение, дающее возможность непосредственно вызвать исключение в коде.

Что такое файл? С точки зрения Python, это объект файловой системы, поддерживающий потоковое чтение и запись.

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

Файл обычно идентифицируется именем, и Python также использует имя файла для его открытия, которое осуществляется встроенной функцией open() :

Функция open() принимает как минимум 1 аргумент — имя файла — и возвращает объект типа file (также встроенный в Python тип), с которым далее и ведётся работа. Вторым аргументом функции указывается способ работы, то есть чтение или запись; по умолчанию, файл открывается на чтение.

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

Имя файла, связанного с объектом, доступно через атрибут file.name :

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

Чтобы прочитать содержимое файла, используется метод file.read() . Он возвращает Python-строку ( str ) состоящую из всего содержимого файла, либо если передать ему 1 аргумент — целое число N, то строка будет состоять из первых N байт файла (либо файла целиком, если его размер меньше N байт).

Можно написать программу из 2 строк, которая выведет собственный код, для этого достаточно сохранить её в файл например program1.py и написать:

Указатель позиции в файле

Если вызвать метод file.read() без аргументов более одного раза, то он вернёт пустую строку:

Объяснение этому таково. Файл можно представить как упорядоченную последовательность байт, каждый из которых имеет индекс, начиная с 0 (первый байт) и до «размер файла — 1». При чтении данных из файла, каждый байт условно по очереди передаётся в строку-результат, и индекс (указатель на текущий байт) увеличивается. По окончании чтения, индекс остаётся в том же месте, и следующее чтение начнётся с этого индекса. Если мы уже прочитали весь файл, то логично, что данных после текущего указателя уже нет.

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

Текстовые и бинарные файлы

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

Главное отличие этих видов в семантике доступа: для текстовых файлов имеет смысл построчный доступ, для бинарных — посимвольный или буферизованный.

С точки зрения пользователя, вид файла не всегда имеет значение, скажем, файл с данными xml или json по содержанию является текстовым, но едва ли имеет смысл обрабатывать его построчно, так как данные представляют собой единую структуру. В то же время файл типа doc для пользователя представляет двоичную кодировку текста.

Работа с текстовыми файлами

Типичным текстовым файлом является файл программы на Python. Для построчного чтения текстовых файлов существует метод file.readline() , который читает строку из файла и увеличивает указатель на длину прочитанной строки. При этом конец строки определяется настройками текущей ОС: для Linux концом строки служит символ перевода строки «\n» (или «\x0a» ), для Windows — последовательность «\r\n» (или «\x0d\x0a» ).

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

Для большего удобства построчного чтения файлов целиком, в цикле for мы можем использовать метод file.readlines() :

Или даже ещё проще:

Объект типа файл является итерируемым, как списки и строки, и итерируется по строкам, содержащимся в файле.

Работа с бинарными файлами

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

У бинарных файлов есть ещё одно отличие: мы можем узнать, где сейчас указатель, и передвинуть указатель вручную на нужное место. (То есть, мы можем это делать и в текстовых файлах, но там это бессмысленно.) Для этого предназначены два соответствующих метода: file.tell() и file.seek() .

Первый возвращает индекс байта, на котором сейчас указатель; второй — принимает число-индекс в качестве аргумента и устанавливает указатель на этот индекс.

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

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

Запись может быть двух видов: перезапись (создание файла, если его ещё нет, либо пересоздание файла, если он уже есть) и дозапись (добавление в конец файла, если он есть, либо ошибка IOError в случае отсутствия).

Режим записи обозначается строкой «w» , режим добавления — строкой «a» .

Далее, собственно писать в файл можно исользуя метод file.write() , который принимает параметр — Python-строку с содержимым для записи. При записи, как и при чтении, указатель позиции в файле увеличивается на количество записанных байт.

Однако если просто записать в открытый файл, записанные данные не сохранятся. Для сохранения данных необходимо закрыть файл, это делается методом file.close() .

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

Смешанные режимы открытия файла

Возможно также открыть файл в режиме, совмещающем чтение и запись. Существует три таких режима:

  • чтение с возможностью записи, режим «r+»
  • перезапись с возможностью чтения, режим «w+»
  • дозапись с возможностью чтения, режим «a+»

Они в целом соответствуют своим «основным» режимам.

Некоторые синтаксические конструкции, облегчающие работу с файлами

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

К счастью, в Python можно обойтись куда более простой конструкцией.

Утверждение break даёт команду немедленно выйти из цикла к следующему за ним утверждению, полностью пропустив оставшиеся итерации и также все утверждения, идущие в блоке кода цикла после break .

В данном случае будет выводиться на экран каждая строка до строки, содержащей «end», не включая её, потому что цикл закончится до вывода её на экран.

Утверждение break можно использовать не только в обработке файлов, и не только в цикле for : циклы while также поддерживают его. Но в любом другом блоке кода, который не относится к циклам, использование break является синтаксической ошибкой.

Утверждение continue является дополнением break : оно пропускает все следующие за ним утверждения в блоке кода цикла и переходит к следующей его итерации. В случае с циклом for это означает — к обработке следующего элемента (если он есть), в случае while — к следующей проверке условия.

Его удобно использовать, если нам нужно, наоборот, начать обработку файла с какой-то строки файла или пропустить обработку строки.

Этот код будет пропускать все строки файла до строки, содержащей «start», начиная с неё, он начнёт выводить все те строки, которые не содержат «skip».

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

Контекстный менеджер умеет автоматически выполнять некторые действия по окончанию выполнения определённого контекста, который задаётся конструкцией with :

БЛОК_КОДА в данном случае и является контекстом. Независимо от того, произошли ли ошибки в БЛОКе_КОДА, контекстный менеджер всегда выполнит завершающие действия, а именно для файлов — их закрытие.

Возьмём пример, использованный выше:

Его можно переписать так:

И файл автоматически будет закрыт по окончанию блока кода в with .

Записать в новый текстовый файл числа от 1 до 10 по одному в строке.

  • в файл можно записать только строковые данные.
  • В конец записываемой строки необходимо добавлять символы перевода строки, для Windows это последовательность «\r\n» .

Прочитать из записанного файла числа от 3 до 7 включительно, используя break и continue . В результате должен получиться список из 5 чисел.

Примеры работы с текстовыми файлами

В данной теме представлены примеры записи и чтения информации для текстовых файлов.

Содержание

  • 1. Чтение/запись списка, содержащего n целых чисел
  • 2. Чтение/запись списка, содержащего строки
  • 3. Чтение/запись кортежа, содержащего объекты чисел с плавающей запятой
  • 4. Чтение/запись кортежа содержащего разнотипные объекты
  • 5. Чтение/запись словаря
  • 6. Чтение/запись двумерной матрицы целых чисел, представленной в виде списка
  • 7. Чтение/запись множества, которое содержит целые числа
  • 8. Чтение/запись данных разных типов: список и кортеж

Поиск на других ресурсах:

1. Чтение/запись списка, содержащего n целых чисел

В примере демонстрируются следующие операции:

  • создание списка из 10 случайных чисел;
  • сохранение списка в текстовом файле;
  • чтение из файла в новый список с целью контроля.

Текст программы следующий:

Результат работы программы

2. Чтение/запись списка, содержащего строки

При чтении/записи строк не нужно реализовывать дополнительные преобразования из одного типа в другой, так как данные из файла читаются в виде строк.

Результат работы программы

3. Чтение/запись кортежа, содержащего объекты чисел с плавающей запятой

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

Результат работы программы

Вид файла myfile5.txt

4. Чтение/запись кортежа содержащего разнотипные объекты

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

Результат выполнения программы

5. Чтение/запись словаря

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

Результат работы программы

Вид файла myfile6.txt

6. Чтение/запись двумерной матрицы целых чисел, представленной в виде списка

В примере демонстрируется запись и чтение двумерной матрицы целых чисел размерностью 3*4.

Результат работы программы

Вид файла myfile8.txt

7. Чтение/запись множества, которое содержит целые числа

В примере демонстрируется возможный вариант сохранения множества в текстовом файле

Результат работы программы

Вид файла myfile7.txt

8. Чтение/запись данных разных типов: список и кортеж

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

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

Reading integers from binary file in Python

I’m trying to read a BMP file in Python. I know the first two bytes indicate the BMP firm. The next 4 bytes are the file size. When I execute:

ValueError: invalid literal for int() with base 10: ‘F#\x13’

What I want to do is reading those four bytes as an integer, but it seems Python is reading them as characters and returning a string, which cannot be converted to an integer. How can I do this correctly?

7 Answers 7

The read method returns a sequence of bytes as a string. To convert from a string byte-sequence to binary data, use the built-in struct module: http://docs.python.org/library/struct.html.

Note that unpack always returns a tuple, so struct.unpack(‘i’, fin.read(4))[0] gives the integer value that you are after.

You should probably use the format string ‘<i’ (< is a modifier that indicates little-endian byte-order and standard size and alignment — the default is to use the platform’s byte ordering, size and alignment). According to the BMP format spec, the bytes should be written in Intel/little-endian byte order.

Читать:
Какое значение имеет служебное слово const

Похожие статьи