Как прочитать файл построчно в список?

avatar
Julie Raswick
18 июля 2010 в 22:25
4115469
28
2026

Как мне прочитать каждую строку файла в Python и сохранить каждую строку как элемент в списке?

Я хочу читать файл построчно и добавлять каждую строку в конец списка.

Источник

Ответы (28)

avatar
LogicalBranch
20 апреля 2019 в 14:44
2

Вот вспомогательный класс Python (3) библиотеки , который я использую для упрощения файлового ввода-вывода:

import os

# handle files using a callback method, prevents repetition
def _FileIO__file_handler(file_path, mode, callback = lambda f: None):
  f = open(file_path, mode)
  try:
    return callback(f)
  except Exception as e:
    raise IOError("Failed to %s file" % ["write to", "read from"][mode.lower() in "r rb r+".split(" ")])
  finally:
    f.close()


class FileIO:
  # return the contents of a file
  def read(file_path, mode = "r"):
    return __file_handler(file_path, mode, lambda rf: rf.read())

  # get the lines of a file
  def lines(file_path, mode = "r", filter_fn = lambda line: len(line) > 0):
    return [line for line in FileIO.read(file_path, mode).strip().split("\n") if filter_fn(line)]

  # create or update a file (NOTE: can also be used to replace a file's original content)
  def write(file_path, new_content, mode = "w"):
    return __file_handler(file_path, mode, lambda wf: wf.write(new_content))

  # delete a file (if it exists)
  def delete(file_path):
    return os.remove() if os.path.isfile(file_path) else None

Затем вы должны использовать функцию FileIO.lines, например:

file_ext_lines = FileIO.lines("./path/to/file.ext"):
for i, line in enumerate(file_ext_lines):
  print("Line {}: {}".format(i + 1, line))

Помните, что параметры mode ("r" по умолчанию) и filter_fn (по умолчанию проверяет наличие пустых строк) являются необязательными.

Вы даже можете удалить методы read, write и delete и просто оставить FileIO.lines или даже превратить его в отдельный метод под названием read_lines.

Mark Amery
29 декабря 2019 в 13:27
0

Действительно ли lines = FileIO.lines(path) проще, чем with open(path) as f: lines = f.readlines(), чтобы оправдать существование этого помощника? Вы экономите примерно 17 символов на звонок. (И в большинстве случаев из соображений производительности и памяти вы захотите перебрать файловый объект напрямую вместо того, чтобы читать его строки в списке, так что вы даже не захотите часто использовать это!) Я часто фанат создания небольших служебных функций, но мне кажется, что это просто напрасное создание нового способа написать что-то, что и без того короткое и простое с помощью стандартной библиотеки дает нам.

AMC
9 января 2020 в 18:53
0

В дополнение к тому, что сказал @MarkAmery, зачем использовать для этого класс?

avatar
simhumileco
14 марта 2019 в 14:28
7

Проще всего сделать это с некоторыми дополнительными преимуществами:

lines = list(open('filename'))

или

lines = tuple(open('filename'))

или

lines = set(open('filename'))

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

Ниже я добавил важное дополнение от @MarkAmery :

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

В CPython (обычная реализация Python , которую использует большинство людей), это не проблема, так как файловый объект будет немедленно удален из мусора, и это будет закройте файл, но, тем не менее, обычно рекомендуется делать что-то вроде :

with open('filename') as f: lines = list(f) 

, чтобы файл был закрыт независимо от того, какую реализацию Python вы используете.

Mark Amery
29 декабря 2019 в 13:58
3

Поскольку вы не вызываете .close для объекта файла и не используете инструкцию with, в некоторых реализациях Python файл может не закрываться после чтения, и ваш процесс будет пропускать дескриптор открытого файла. В CPython (обычная реализация Python, которую использует большинство людей) это не проблема, поскольку файловый объект будет немедленно обработан сборщиком мусора, и это закроет файл, но, тем не менее, обычно считается лучшей практикой делать что-то вроде with open('filename') as f: lines = list(f) чтобы файл был закрыт независимо от того, какую реализацию Python вы используете.

simhumileco
30 декабря 2019 в 12:22
0

Спасибо за отличный комментарий @MarkAmery! Я очень ценю это.

AMC
9 января 2020 в 18:44
1

@simhumileco Почему лучшее (правильное) решение остается последним?

simhumileco
9 января 2020 в 21:27
0

@AMC, потому что во-первых, я хотел показать простейшие способы и для последовательности рассуждений.

simhumileco
9 января 2020 в 22:22
0

Кроме того, я надеюсь, что мой ответ будет кратким и легким для чтения.

avatar
jeanggi90
16 января 2019 в 21:30
4

В случае, если в документе также есть пустые строки, мне нравится читать содержимое и передавать его через filter, чтобы предотвратить пустые строковые элементы

with open(myFile, "r") as f:
    excludeFileContent = list(filter(None, f.read().splitlines()))
AMC
9 января 2020 в 18:50
1

Это непифонично, будьте осторожны.

avatar
Siddharth Satpathy
19 декабря 2018 в 01:47
2

Я бы попробовал один из нижеперечисленных способов. Файл примера, который я использую, имеет имя dummy.txt. Вы можете найти файл здесь. Я предполагаю, что файл находится в том же каталоге, что и код (вы можете изменить fpath, чтобы включить правильное имя файла и путь к папке.)

В обоих приведенных ниже примерах список, который вам нужен, представлен как lst.

1.> Первый метод :

fpath = 'dummy.txt'
with open(fpath, "r") as f: lst = [line.rstrip('\n \t') for line in f]

print lst
>>>['THIS IS LINE1.', 'THIS IS LINE2.', 'THIS IS LINE3.', 'THIS IS LINE4.']

2.> Во втором методе можно использовать модуль csv.reader <57826354328226> стандартной библиотеки Python:

import csv
fpath = 'dummy.txt'
with open(fpath) as csv_file:
    csv_reader = csv.reader(csv_file, delimiter='   ')
    lst = [row[0] for row in csv_reader] 

print lst
>>>['THIS IS LINE1.', 'THIS IS LINE2.', 'THIS IS LINE3.', 'THIS IS LINE4.']

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

Charlie Harding
1 января 2019 в 19:16
1

В чем преимущество второго подхода? Зачем вызывать дополнительную библиотеку, которая добавляет крайние случаи (разделитель и кавычки)?

AMC
9 января 2020 в 18:52
0

Для чего нужен аргумент delimiter=' '?

avatar
Aaron Hall
16 мая 2018 в 20:17
4

Схема и резюме

С помощью filename, обрабатывая файл из объекта Path(filename), или напрямую с помощью open(filename) as f, выполните одно из следующих действий:

  • list(fileinput.input(filename))
  • используя with path.open() as f, звоните f.readlines()
  • list(f)
  • path.read_text().splitlines()
  • path.read_text().splitlines(keepends=True)
  • перебирать fileinput.input или f и list.append каждую строку по одной за раз
  • передать f связанному методу list.extend
  • использовать f в понимании списка

Я объясню варианты использования для каждого из них ниже.

Как в Python читать файл построчно?

Это отличный вопрос. Сначала создадим несколько примеров данных:

from pathlib import Path
Path('filename').write_text('foo\nbar\nbaz')

Файловые объекты являются ленивыми итераторами, поэтому просто перебирайте их.

filename = 'filename'
with open(filename) as f:
    for line in f:
        line # do something with the line

В качестве альтернативы, если у вас несколько файлов, используйте fileinput.input, еще один ленивый итератор. Всего одним файлом:

import fileinput

for line in fileinput.input(filename): 
    line # process the line

или для нескольких файлов передайте ему список имен файлов:

for line in fileinput.input([filename]*2): 
    line # process the line

Опять же, f и fileinput.input выше оба являются / возвращают ленивые итераторы. Вы можете использовать итератор только один раз, поэтому, чтобы предоставить функциональный код, избегая многословия, я буду использовать немного более сжатый fileinput.input(filename) where по поводу отсюда.

Как в Python построчно прочитать файл в список?

А, но вы почему-то хотите, чтобы это было в списке? Если возможно, я бы этого избежал. Но если вы настаиваете ... просто передайте результат fileinput.input(filename) в list:

list(fileinput.input(filename))

Другой прямой ответ - вызов f.readlines, который возвращает содержимое файла (до необязательного hint количества символов, поэтому можно разбить его на несколько списков таким образом) .

Вы можете добраться до этого файлового объекта двумя способами. Один из способов - передать имя файла встроенной функции open:

filename = 'filename'

with open(filename) as f:
    f.readlines()

или используя новый объект Path из модуля pathlib (который я очень полюбил и буду использовать с этого момента):

from pathlib import Path

path = Path(filename)

with path.open() as f:
    f.readlines()

list также будет использовать файловый итератор и возвращать список - тоже довольно прямой метод:

with path.open() as f:
    list(f)

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

path.read_text().splitlines()

Если вы хотите сохранить символы новой строки, передайте keepends=True:

path.read_text().splitlines(keepends=True)

Я хочу читать файл построчно и добавлять каждую строку в конец списка.

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

Использование list.append позволит вам фильтровать или работать с каждой строкой перед ее добавлением:

line_list = []
for line in fileinput.input(filename):
    line_list.append(line)

line_list

Использование list.extend было бы немного более прямым и, возможно, полезным, если у вас есть уже существующий список:

line_list = []
line_list.extend(fileinput.input(filename))
line_list

Или, что более идиоматично, мы могли бы вместо этого использовать понимание списка, а также отображать и фильтровать его, если желательно:

[line for line in fileinput.input(filename)]

Или, что еще точнее, чтобы замкнуть круг, просто передайте его в список, чтобы создать новый список напрямую, не работая со строками:

list(fileinput.input(filename))

Заключение

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

То есть предпочтительнее fileinput.input или with path.open() as f.

avatar
LangeHaare
30 апреля 2018 в 17:41
36

Представленный в Python 3.4, pathlib имеет действительно удобный метод чтения текста из файлов, а именно:

from pathlib import Path
p = Path('my_text_file')
lines = p.read_text().splitlines()

(Вызов splitlines превращает его из строки, содержащей все содержимое файла, в список строк в файле).

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

avatar
Daniel
29 марта 2018 в 10:30
2

Мне нравится использовать следующее. Немедленное чтение строк.

contents = []
for line in open(filepath, 'r').readlines():
    contents.append(line.strip())

Или используя понимание списка:

contents = [line.strip() for line in open(filepath, 'r').readlines()]
Eric O Lebigot
23 октября 2018 в 10:58
2

Нет необходимости в readlines(), что даже приводит к потере памяти. Вы можете просто удалить его, поскольку итерация по (текстовому) файлу дает каждую строку по очереди.

Aran-Fey
29 октября 2018 в 17:50
2

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

avatar
MSeifert
16 января 2018 в 22:33
46

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

  • Откройте файл
  • Прочитать файл
  • Сохранить содержимое как список

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

lst = list(open(filename))

Однако я добавлю еще несколько пояснений.

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

Я предполагаю, что вы хотите открыть определенный файл и не имеете дело напрямую с дескриптором файла (или дескриптором, подобным файлу). Наиболее часто используемая функция для открытия файла в Python - open, она принимает один обязательный аргумент и два необязательных аргумента в Python 2.7:

  • Имя файла
  • Режим
  • Буферизация (я проигнорирую этот аргумент в этом ответе)

Имя файла должно быть строкой, представляющей путь к файлу . Например:

open('afile')   # opens the file named afile in the current working directory
open('adir/afile')            # relative path (relative to the current working directory)
open('C:/users/aname/afile')  # absolute path (windows)
open('/usr/local/afile')      # absolute path (linux)

Обратите внимание, что необходимо указать расширение файла. Это особенно важно для пользователей Windows, поскольку расширения файлов, такие как .txt или .doc и т. Д., Скрыты по умолчанию при просмотре в проводнике.

Второй аргумент - mode, по умолчанию это r, что означает «только для чтения». Это именно то, что вам нужно в вашем случае.

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

Для чтения файла вы можете опустить mode или передать его явно:

open(filename)
open(filename, 'r')

Оба откроют файл в режиме только для чтения. Если вы хотите читать двоичный файл в Windows, вам необходимо использовать режим rb:

open(filename, 'rb')

На других платформах 'b' (двоичный режим) просто игнорируется.


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

Хотя вы можете использовать:

f = open(filename)
# ... do stuff with f
f.close()

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

f = open(filename)
# nothing in between!
try:
    # do stuff with f
finally:
    f.close()

Однако Python предоставляет диспетчеры контекста с более красивым синтаксисом (но для open он почти идентичен try и finally выше):

with open(filename) as f:
    # do stuff with f
# The file is always closed after the with-scope ends.

Последний подход - это рекомендованный подход для открытия файла в Python!

Чтение файла

Хорошо, вы открыли файл, как его читать?

Функция open возвращает объект file и поддерживает итерационный протокол Pythons. Каждая итерация даст вам строку:

with open(filename) as f:
    for line in f:
        print(line)

Будет напечатана каждая строка файла. Однако обратите внимание, что каждая строка будет содержать символ новой строки \n в конце (вы можете проверить, построен ли ваш Python с помощью универсальной поддержки новой строки - в противном случае у вас также может быть \r\n в Windows или \r на Mac как символы новой строки). Если вы этого не хотите, вы можете просто удалить последний символ (или последние два символа в Windows):

with open(filename) as f:
    for line in f:
        print(line[:-1])

Но последняя строка не обязательно имеет завершающую новую строку, поэтому не следует ее использовать. Можно проверить, заканчивается ли он завершающим символом новой строки, и если да, то удалить его:

with open(filename) as f:
    for line in f:
        if line.endswith('\n'):
            line = line[:-1]
        print(line)

Но вы можете просто удалить все пробелы (включая символ \n) с конца строки , это также удалит все остальные завершающие пробелы, чтобы они были будьте осторожны, если они важны:

with open(filename) as f:
    for line in f:
        print(f.rstrip())

Однако, если строки заканчиваются на \r\n («новые строки» Windows), этот .rstrip() также позаботится о \r!

Сохранить содержимое как список

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

with open(filename) as f:
    lst = list(f)

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

with open(filename) as f:
    lst = [line.rstrip() for line in f]

Или еще проще: метод .readlines() объекта file по умолчанию возвращает list из строк:

with open(filename) as f:
    lst = f.readlines()

Это также будет включать завершающие символы новой строки, если они вам не нужны, я бы рекомендовал подход [line.rstrip() for line in f], потому что он позволяет избежать хранения двух списков, содержащих все строки в памяти.

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

with open(filename) as f:
    lst = f.read().split('\n')

или:

with open(filename) as f:
    lst = f.read().splitlines()

Они автоматически обрабатывают завершающие символы новой строки, поскольку символ split не включен. Однако они не идеальны, потому что вы храните файл как строку и как список строк в памяти!

Сводка

  • Используйте with open(...) as f при открытии файлов, потому что вам не нужно заботиться о закрытии файла самостоятельно, и он закрывает файл, даже если происходит какое-то исключение.
  • Объекты file поддерживают протокол итераций, поэтому построчное чтение файла так же просто, как for line in the_file_object:.
  • Всегда просматривайте документацию на предмет доступных функций / классов. В большинстве случаев есть идеальное соответствие для задачи или, по крайней мере, одно или два хороших. В этом случае очевидным выбором будет readlines(), но если вы хотите обработать строки перед сохранением их в списке, я бы рекомендовал простое понимание списка.
AMC
9 января 2020 в 18:40
0

Последний подход - это рекомендуемый подход для открытия файла в Python! Почему же тогда последний? Разве подавляющее большинство людей не взглянут на первые несколько строк ответа, прежде чем двигаться дальше?

MSeifert
9 января 2020 в 19:14
0

@AMC Я не особо задумывался над этим, когда писал ответ. Как вы думаете, я должен поставить это в начале ответа?

AMC
9 января 2020 в 19:16
0

Это может быть лучше, да. Я также только что заметил, что вы упоминаете Python 2, так что его тоже можно обновить.

MSeifert
9 января 2020 в 19:28
0

А вопрос изначально был помечен как python-2.x. Возможно, имеет смысл обновить его в более общем плане. Я посмотрю, приду ли я к этому в следующий раз. Спасибо за ваши предложения. Очень признателен!

avatar
Martin Thoma
16 января 2018 в 19:42
27

Чтение и запись текстовых файлов с помощью Python 2 и Python 3; он работает с Unicode

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# Define data
lines = ['     A first string  ',
         'A Unicode sample: €',
         'German: äöüß']

# Write text file
with open('file.txt', 'w') as fp:
    fp.write('\n'.join(lines))

# Read text file
with open('file.txt', 'r') as fp:
    read_lines = fp.readlines()
    read_lines = [line.rstrip('\n') for line in read_lines]

print(lines == read_lines)

На заметку:

  • with - это так называемый менеджер контекста. Обеспечивает повторное закрытие открытого файла.
  • Все решения здесь, которые просто создают .strip() или .rstrip(), не смогут воспроизвести lines, поскольку они также удаляют пустое пространство.

Общие окончания файлов

.txt

Более продвинутая запись / чтение файлов

  • CSV: сверхпростой формат (чтение и запись)
  • JSON: удобен для записи удобочитаемых данных; ОЧЕНЬ часто используется (чтение и запись)
  • YAML: YAML - это надмножество JSON, но его легче читать (чтение и запись, сравнение JSON и YAML)
  • pickle: формат сериализации Python (чтение и запись)
  • MessagePack (пакет Python): более компактное представление (чтение и запись)
  • HDF5 (пакет Python): подходит для матриц (чтение и запись)
  • XML: тоже существует * вздох * (чтение и запись)

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

  • Поддержка других языков программирования
  • Скорость чтения / записи
  • Компактность (размер файла)

См. Также: Сравнение форматов сериализации данных

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

avatar
jasonleonhard
29 августа 2017 в 23:53
1

Версия командной строки

#!/bin/python3
import os
import sys
abspath = os.path.abspath(__file__)
dname = os.path.dirname(abspath)
filename = dname + sys.argv[1]
arr = open(filename).read().split("\n") 
print(arr)

Запустить с:

python3 somefile.py input_file_name.txt
mah
18 марта 2021 в 23:29
0

С какой стати вы хотите, чтобы текстовый файл находился в том же каталоге, в котором находится ваш скрипт Python? Просто open(sys.argv[1]) вместо этого, и он будет работать независимо от указанного относительного или абсолютного пути, и ему все равно, где находится ваш скрипт.

avatar
PythonProgrammi
26 апреля 2017 в 04:57
103

Содержимое текстового файла:

line 1
line 2
line 3

Мы можем использовать этот скрипт Python в том же каталоге, что и txt выше

>>> with open("myfile.txt", encoding="utf-8") as file:
...     x = [l.rstrip("\n") for l in file]
>>> x
['line 1','line 2','line 3']

Использование добавления:

x = []
with open("myfile.txt") as file:
    for l in file:
        x.append(l.strip())

Или:

>>> x = open("myfile.txt").read().splitlines()
>>> x
['line 1', 'line 2', 'line 3']

Или:

>>> x = open("myfile.txt").readlines()
>>> x
['linea 1\n', 'line 2\n', 'line 3\n']

Или:

def print_output(lines_in_textfile):
    print("lines_in_textfile =", lines_in_textfile)

y = [x.rstrip() for x in open("001.txt")]
print_output(y)

with open('001.txt', 'r', encoding='utf-8') as file:
    file = file.read().splitlines()
    print_output(file)

with open('001.txt', 'r', encoding='utf-8') as file:
    file = [x.rstrip("\n") for x in file]
    print_output(file)

вывод:

lines_in_textfile = ['line 1', 'line 2', 'line 3']
lines_in_textfile = ['line 1', 'line 2', 'line 3']
lines_in_textfile = ['line 1', 'line 2', 'line 3']
Mausy5043
3 июня 2018 в 08:53
0

требуется ли encoding="utf-8"?

PythonProgrammi
3 июня 2018 в 09:55
0

@ Mausy5043 нет, но когда вы читаете текстовый файл, у вас может быть какой-то странный символ (особенно на итальянском)

Eric O Lebigot
23 октября 2018 в 10:57
1

read().splitlines() предоставляется вам Python: это просто readlines() (что, вероятно, быстрее, поскольку это менее расточительно).

craq
4 июня 2020 в 02:50
3

@EricOLebigot из показанных примеров, похоже, что read().splitlines() и readlines() не производят одинаковый результат. Вы уверены, что они эквивалентны?

PythonProgrammi
4 июня 2020 в 03:59
2

Если вы используете только строки чтения, вам нужно использовать метод полосы, чтобы избавиться от \ n в тексте, поэтому я изменил последние примеры, используя понимание списка, чтобы в обоих случаях вывод был одинаковым. Итак, если вы используете read (). Readlines (), у вас будет «чистый» элемент со строкой и без символа новой строки, в противном случае вы должны сделать то, что вы видите в приведенном выше коде.

Eric O Lebigot
5 июня 2020 в 06:06
1

Действительно. Обратите внимание, что в приведенном выше коде все strip() должно быть rstrip("\n"), или пробелы вокруг строки удаляются. Кроме того, нет смысла делать readlines() в понимании списка: лучше просто перебирать файл, так как это не тратит время и память на создание промежуточного списка строк.

Abhijeet Singh
14 декабря 2020 в 15:39
0

с open ("Beautify.txt") как file_in: lines = [] для строки в file_in: lines.append (line.replace ('\ n', ''))

avatar
pambda
11 марта 2017 в 08:49
11

Если вы хотите столкнуться с очень большим / огромным файлом и хотите читать быстрее (представьте, что вы участвуете в соревновании по кодированию Topcoder / Hackerrank), вы можете прочитать значительно больший фрагмент строк в буфер памяти за один раз, а не просто итерация строка за строкой на уровне файла.

buffersize = 2**16
with open(path) as f: 
    while True:
        lines_buffer = f.readlines(buffersize)
        if not lines_buffer:
            break
        for line in lines_buffer:
            process(line)
Newskooler
6 апреля 2017 в 08:40
0

что делает процесс (линия)? Я получаю сообщение об ошибке, что такая переменная не определена. Я предполагаю, что что-то нужно импортировать, и я попытался импортировать multiprocessing.Process, но я думаю, что это не так. Не могли бы вы уточнить? Спасибо

Khanal
26 апреля 2017 в 13:27
1

process(line) - это функция, которую необходимо реализовать для обработки данных. например, вместо этой строки, если вы используете print(line), он будет печатать каждую строку из lines_buffer.

David Dehghan
30 июня 2018 в 10:28
0

f.readlines (buffersize) возвращает неизменяемый буфер. если вы хотите напрямую читать в свой буфер, вам нужно использовать функцию readinto (). Я буду намного быстрее.

avatar
Abdullah Bilal
9 сентября 2016 в 09:13
15

Просто используйте функции splitlines (). Вот пример.

inp = "file.txt"
data = open(inp)
dat = data.read()
lst = dat.splitlines()
print lst
# print(lst) # for python 3

В выводе будет список строк.

Mark Amery
29 декабря 2019 в 14:10
0

Неэффективность памяти по сравнению с использованием .readlines(). Это помещает в память сразу две копии содержимого файла (одну как одну огромную строку, другую как список строк).

physicalattraction
3 сентября 2020 в 16:04
1

Но data.read().splitlines() читать намного легче, и память не всегда вызывает беспокойство по сравнению с простотой чтения кода.

avatar
Zero
30 марта 2016 в 15:50
4

Используйте это:

import pandas as pd
data = pd.read_csv(filename) # You can also add parameters such as header, sep, etc.
array = data.values

data - это тип фрейма данных, который использует значения для получения ndarray. Вы также можете получить список, используя array.tolist().

AMC
9 января 2020 в 18:51
0

pandas.read_csv() предназначен для чтения данных CSV , как это здесь уместно?

avatar
DevShark
25 февраля 2016 в 09:13
162

Вы можете просто сделать следующее, как было предложено:

with open('/your/path/file') as f:
    my_lines = f.readlines()

Обратите внимание, что у этого подхода есть 2 недостатка:

1) Вы сохраняете все строки в памяти. В общем случае это очень плохая идея. Файл может быть очень большим, и у вас может закончиться память. Даже если он небольшой, это просто пустая трата памяти.

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

Лучшим подходом для общего случая будет следующий:

with open('/your/path/file') as f:
    for line in f:
        process(line)

Где вы определяете свою функцию процесса так, как хотите. Например:

def process(line):
    if 'save the world' in line.lower():
         superman.save_the_world()

(Реализация класса Superman оставлена ​​в качестве упражнения для вас).

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

Ephexx
17 мая 2016 в 21:37
5

Это было именно то, что мне было нужно - и спасибо за объяснение недостатков. Как новичку в Python, здорово понимать, почему решение есть решение. Ваше здоровье!

Corey Goldberg
12 декабря 2016 в 23:19
0

в вопросе не говорится о необходимости обрабатывать каждую строку, поэтому этот ответ дает нерелевантную информацию

DevShark
13 декабря 2016 в 07:31
5

Подумай еще немного, Кори. Вы действительно когда-нибудь хотите, чтобы ваш компьютер читал каждую строку, ничего не делая с этими строками? Конечно, вы понимаете, что вам всегда нужно так или иначе их обрабатывать.

Corey Goldberg
13 декабря 2016 в 15:06
0

@DevShark всегда? это просто ложь.

DevShark
14 декабря 2016 в 10:22
5

С линиями всегда нужно что-то делать. Это может быть так же просто, как распечатать линии или подсчитать их. Нет никакого смысла в том, чтобы ваш процесс читал строки в памяти, но ничего не делал с ними.

Corey Goldberg
23 июня 2017 в 16:55
0

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

DevShark
23 июня 2017 в 19:40
3

С ними всегда нужно что-то делать. Я думаю, что вы пытаетесь сказать, что вы можете применить функцию ко всем сразу, а не по отдельности. Иногда это действительно так. Но это очень неэффективно с точки зрения памяти и мешает вам читать файлы, если его размер больше, чем ваш Ram. Вот почему типичные парсеры обычно работают так, как я описал.

Pierre Monico
10 августа 2017 в 11:56
0

Хороший подход, но если быть точным: в этом контексте «обработка строк» ​​не изменит их в исходном файле. Вам нужно скопировать их в другой файл, если вам нужно их изменить и сохранить.

DevShark
14 сентября 2017 в 09:17
2

@PierreOcinom, это правильно. Учитывая, что файл открывается в режиме только для чтения, вы не можете изменить исходный файл с помощью приведенного выше кода. Чтобы открыть файл для чтения и записи, используйте open('file_path', 'r+')

Tirtha R
2 марта 2018 в 23:15
2

Я проверил профиль памяти обоих способов, используя описанную здесь процедуру. Использование памяти намного лучше, когда каждая строка считывается из файла и обрабатывается, как предлагает @DevShark. Хранение всех строк в объекте коллекции - это , а не хорошая идея, если память является ограничением или файл большой. Время выполнения одинаково в обоих подходах.

DevShark
24 июля 2018 в 11:50
0

Спасибо за подсчет. Это то, что ожидалось.

JeramieH
12 сентября 2018 в 19:01
0

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

DevShark
12 сентября 2018 в 19:45
0

Мое утверждение было «вам всегда нужно что-то делать с линиями», и ваш пример иллюстрирует это: вы добавляете их в набор. Я думаю, вы утверждаете, что написанный мной код - не единственный способ делать что-то. Это правильно. Чтобы загрузить их все в набор, вам может больше понравиться другой подход - прочитать все строки за один раз.

avatar
asampat3090
20 июля 2015 в 17:33
2

Вы также можете использовать команду loadtxt в NumPy. Это проверяет меньшее количество условий, чем genfromtxt, поэтому может быть быстрее.

import numpy
data = numpy.loadtxt(filename, delimiter="\n")
avatar
Pedro Lobito
20 апреля 2015 в 05:53
221

Согласно методам Python файловых объектов, самый простой способ преобразовать текстовый файл в list - это:

with open('file.txt') as f:
    my_list = list(f)
    # my_list = [x.rstrip() for x in f] # remove line breaks

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

with open('file.txt') as f:
    for line in f:
       ...

Старый ответ:

Использование with и readlines():

with open('file.txt') as f:
    lines = f.readlines()

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

lines = open('file.txt').readlines()

традиционный способ:

f = open('file.txt') # Open file on read mode
lines = f.read().splitlines() # List with stripped line-breaks
f.close() # Close file
oneturkmen
2 июня 2021 в 20:59
1

Прокомментированная строка в первом примере # my_list = [x.rstrip() for x in f] # remove line breaks должна быть # my_list = [x.rstrip() for x in my_list] # remove line breaks.

mightyandweakcoder
9 сентября 2021 в 14:33
2

@oneturkmen нет, он прав. он перебирает строки в файле. Вы были бы правы, если бы строка была после предложения 'with'

avatar
Jean-Francois T.
6 февраля 2015 в 03:34
20

Самый простой способ сделать это

Простой способ:

  1. Прочитать весь файл как строку
  2. Разделить строку построчно

В одной строке это даст:

lines = open('C:/path/file.txt').read().splitlines()

Однако это довольно неэффективный способ, так как при этом в памяти будут храниться 2 версии контента (возможно, это не большая проблема для небольших файлов, но все же). [Спасибо, Марк Амери].

Есть 2 более простых способа:

  1. Использование файла в качестве итератора
lines = list(open('C:/path/file.txt'))
# ... or if you want to have a list without EOL characters
lines = [l.rstrip() for l in open('C:/path/file.txt')]
  1. Если вы используете Python 3.4 или выше, лучше используйте pathlib, чтобы создать путь к вашему файлу, который вы могли бы использовать для других операций в вашей программе:
from pathlib import Path
file_path = Path("C:/path/file.txt") 
lines = file_path.read_text().split_lines()
# ... or ... 
lines = [l.rstrip() for l in file_path.open()]
Mark Amery
29 декабря 2019 в 14:12
1

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

Jean-Francois T.
31 декабря 2019 в 10:00
0

@MarkAmery Верно. Спасибо, что подчеркнули это. Я обновил свой ответ.

avatar
Johnny
20 декабря 2014 в 18:31
44

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


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

infile = open('my_file.txt', 'r')  # Open the file for reading.

data = infile.read()  # Read the contents of the file.

infile.close()  # Close the file since we're done using it.

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

# Open the file for reading.
with open('my_file.txt', 'r') as infile:

    data = infile.read()  # Read the contents of the file into memory.

Теперь нам нужно сосредоточиться на внесении этих данных в список Python , поскольку они являются повторяемыми, эффективными и гибкими. В вашем случае желаемая цель - вывести каждую строку текстового файла в отдельный элемент. Для этого мы будем использовать метод splitlines () следующим образом:

# Return a list of the lines, breaking at line boundaries.
my_list = data.splitlines()

Конечный продукт:

# Open the file for reading.
with open('my_file.txt', 'r') as infile:

    data = infile.read()  # Read the contents of the file into memory.

# Return a list of the lines, breaking at line boundaries.
my_list = data.splitlines()

Тестирование нашего кода:

  • Содержимое текстового файла:
     A fost odatã ca-n povesti,
     A fost ca niciodatã,
     Din rude mãri împãrãtesti,
     O prea frumoasã fatã.
  • Распечатать отчеты для целей тестирования:
    print my_list  # Print the list.

    # Print each line in the list.
    for line in my_list:
        print line

    # Print the fourth element in this list.
    print my_list[3]
  • Вывод (другой вид из-за символов Юникода):
     ['A fost odat\xc3\xa3 ca-n povesti,', 'A fost ca niciodat\xc3\xa3,',
     'Din rude m\xc3\xa3ri \xc3\xaemp\xc3\xa3r\xc3\xa3testi,', 'O prea
     frumoas\xc3\xa3 fat\xc3\xa3.']

     A fost odatã ca-n povesti, A fost ca niciodatã, Din rude mãri
     împãrãtesti, O prea frumoasã fatã.

     O prea frumoasã fatã.
avatar
user1833244
27 мая 2014 в 12:21
30

Вот еще один вариант использования списков в файлах;

lines = [line.rstrip() for line in open('file.txt')]

Этот способ должен быть более эффективным, поскольку большая часть работы выполняется внутри интерпретатора Python.

mklement0
22 мая 2015 в 16:39
11

rstrip() потенциально удаляет все завершающие пробелы, а не только \n; используйте .rstrip('\n').

Mark Amery
29 декабря 2019 в 14:30
1

Это также не гарантирует, что файл будет закрыт после чтения во всех реализациях Python (хотя в CPython, основной реализации Python, так и будет).

AMC
9 января 2020 в 18:41
1

Этот способ должен быть более эффективным, поскольку большая часть работы выполняется внутри интерпретатора Python. Что это означает?

avatar
Eneko Alonso
2 марта 2014 в 04:22
226

Если вы хотите, чтобы \n включал:

with open(fname) as f:
    content = f.readlines()

Если вы не хотите, чтобы \n включал:

with open(fname) as f:
    content = f.read().splitlines()
Joke Huang
11 июля 2021 в 14:47
0

отлично, он содержит пустую строку между каждой строкой. '1\n2\n3\n' => [ '1', '', '2', '', '3', '' ]

avatar
moldovean
12 января 2014 в 10:58
28
f = open("your_file.txt",'r')
out = f.readlines() # will append in the list out

Теперь выходная переменная представляет собой список (массив) того, что вы хотите. Вы можете либо сделать:

for line in out:
    print (line)

Или:

for line in f:
    print (line)

Вы получите те же результаты.

avatar
oliland
22 ноября 2013 в 14:57
25

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

# reader.py
import fileinput

content = []
for line in fileinput.input():
    content.append(line.strip())

fileinput.close()

Передайте ему файлы так:

$ python reader.py textfile.txt 

Подробнее здесь: http://docs.python.org/2/library/fileinput.html

avatar
atomh33ls
18 июня 2013 в 10:17
25

Другой вариант - numpy.genfromtxt, например:

import numpy as np
data = np.genfromtxt("yourfile.dat",delimiter="\n")

Это сделает data массивом NumPy с таким количеством строк, как в вашем файле.

avatar
SilentGhost
18 июля 2010 в 22:28
2444

Этот код прочитает весь файл в память и удалит все пробелы (новые строки и пробелы) в конце каждой строки:

with open(filename) as file:
    lines = file.readlines()
    lines = [line.rstrip() for line in lines]

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

with open(filename) as file:
    for line in file:
        print(line.rstrip())

В Python 3.8 и выше вы можете использовать цикл while с оператором моржа следующим образом:

with open(filename) as file:
    while (line := file.readline().rstrip()):
        print(line)

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

with open(filename, 'r', encoding='UTF-8') as file:
    while (line := file.readline().rstrip()):
        print(line)
DarkCygnus
27 августа 2016 в 03:07
119

В случае, если вы работаете с большими данными, использование readlines() не очень эффективно, поскольку может привести к MemoryError . В этом случае лучше перебирать файл, используя for line in f: и работая с каждой переменной line.

Tirtha R
2 марта 2018 в 23:24
9

Я проверил профиль памяти разными способами, приведенными в ответах, используя процедуру, упомянутую здесь. Использование памяти намного лучше, когда каждая строка считывается из файла и обрабатывается, как предлагает здесь @DevShark. Хранение всех строк в объекте коллекции - это , а не , что является хорошей идеей, если память является ограничением или файл большой. Время выполнения одинаково в обоих подходах.

Gringo Suave
15 июня 2018 в 19:14
8

Кроме того, .rstrip() будет работать немного быстрее, если вы удаляете пробелы с концов строк.

Vishal Gupta
3 июня 2020 в 01:33
4

Oneliner: with open(filename) as f: content = [i.strip() for i in f.readlines()]

Elder Druid
9 декабря 2020 в 20:28
1

open(filename, encoding='utf-8') может помочь

YJiqdAdwTifMxGR
27 декабря 2020 в 16:07
1

@ElderDruid что делать, если кодировка файла не UTF-8?

Timo
24 февраля 2021 в 16:47
1

Я думаю, что readlines() устарел.

SOFe
26 марта 2021 в 09:02
2

@ просто напишите [x.strip() for x in f], не звоня по номеру readlines(). Таким образом, вам не нужно создавать дополнительный список.

Sembei Norimaki
1 сентября 2021 в 15:19
0

Из-за rstrip пустая строка в середине файла прервет цикл, поэтому он не будет читать весь файл

avatar
Felix Kling
18 июля 2010 в 22:28
1106

См. Ввод и вывод:

with open('filename') as f:
    lines = f.readlines()

или с удалением символа новой строки:

with open('filename') as f:
    lines = [line.rstrip() for line in f]
Mark
28 августа 2015 в 07:48
58

Лучше использовать f.read().splitlines(), который удаляет новые строки

becko
10 февраля 2016 в 15:30
1

Безопасна ли вторая версия с for line in open(filename)? То есть файл автоматически закроется?

Brad Hein
3 марта 2016 в 19:45
2

Лучше читать файл по одной строке за раз, а не читать весь файл в память сразу. Это плохо масштабируется с большими входными файлами. См. Ниже ответ Роберта.

Josiah Yoder
7 июля 2017 в 21:31
0

@MFARID «В текстовом режиме при чтении по умолчанию концы строк, зависящие от платформы (\ n в Unix, \ r \ n в Windows) преобразуются только в \ n». (Для Python 3 не менее). Так что rstrip('\r') не нужен.

Ramisa Anjum Aditi
11 мая 2018 в 14:16
2

lines = [x.rstrip('\n') for x in open('data\hsf.txt','r')] Если я напишу так, как я могу закрыть файл после прочтения?

Aaron Hall
16 мая 2018 в 21:25
2

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

Mark Amery
1 сентября 2019 в 18:31
0

@AaronHall «когда у объекта больше нет ссылок на него, он будет собран мусором, а файл закрыт» - это верно для CPython, но не для PyPy. Не все реализации Python немедленно уничтожают объекты, когда на них больше нет ссылок. Таким образом, даже в этом случае уместна передовая практика использования with с open.

Timo
30 января 2021 в 18:58
0

состояние гонки с Silent Ghost ..;)

avatar
robert
18 июля 2010 в 22:27
666

Это более явно, чем необходимо, но делает то, что вы хотите.

with open("file.txt") as file_in:
    lines = []
    for line in file_in:
        lines.append(line)
JohannesB
19 сентября 2018 в 12:44
37

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

Elias Strehle
4 октября 2018 в 12:48
3

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

OrigamiEye
1 декабря 2018 в 15:39
0

@haccks это лучше, потому что он не загружает весь файл в память или есть еще?

AMC
9 января 2020 в 18:31
8

Примечание. Это решение не удаляет символы новой строки.

andrebrait
4 мая 2020 в 20:33
9

Это решение загружает в память весь файл. Я не знаю, почему люди думают, что это не так.

João Monteiro
10 июня 2020 в 23:15
2

@andrebrait Он загружает весь файл в строки [] по выбору, но может загружать просто строку за строкой.

avatar
Noctis Skytower
18 июля 2010 в 22:27
299

Это даст "массив" строк из файла.

lines = tuple(open(filename, 'r'))

open возвращает файл, который можно повторять. Когда вы перебираете файл, вы получаете строки из этого файла. tuple может взять итератор и создать для вас экземпляр кортежа из итератора, который вы ему предоставили. lines - кортеж, созданный из строк файла.

Marshall Farrier
11 декабря 2014 в 07:16
1

Это лучший ответ, если вы хотите, чтобы там были символы новой строки. Есть ли способ изменить его, чтобы убрать их, не нарушая красивой простоты этой версии?

Noctis Skytower
11 декабря 2014 в 13:56
36

@MarshallFarrier Попробуйте вместо этого lines = open(filename).read().split('\n').

Vanuan
3 января 2015 в 02:21
23

он закрывает файл?

Noctis Skytower
3 января 2015 в 13:06
8

@Vanuan Поскольку после выполнения строки не остается ссылки на файл, деструктор должен автоматически закрыть файл.

jaynp
13 мая 2015 в 05:59
36

@NoctisSkytower Я считаю, что lines = open(filename).read().splitlines() немного чище, и я считаю, что он также лучше обрабатывает окончания строк DOS.

Noctis Skytower
13 мая 2015 в 20:53
4

@ dal102 Да, я согласен с вами и желаю, чтобы я узнал о методе splitlines раньше. Однако обратите внимание, что аргумент newline функции open равен None, поэтому включен универсальный режим новой строки и в этом случае допустимо разделение на '\n'. Однако особенно интересно то, что существует метод bytes.splitlines. Это дает возможность имитировать универсальный режим новой строки при открытии файла в двоичном режиме. На самом деле вам не нужно открывать файл в текстовом режиме, чтобы легко разделить данные файла по границам строк и избежать импорта модуля re.

mklement0
22 мая 2015 в 17:21
4

Это элегантно (за исключением того, что в самом ответе стоит отметить, что завершающий \n сохраняется в каждом элементе), но мне любопытно, почему вы выбрали tuple() вместо list(). Судя по моим неофициальным тестам, list() работает немного лучше (вероятно, не имеет большого значения). list(), в отличие от tuple(), вернет изменяемую последовательность (которая может быть, а может и не быть желательной).

Noctis Skytower
4 января 2016 в 16:17
9

@ mklement0 Предполагая, что файл состоит из 1000 строк, list занимает примерно на 13,22% больше места, чем tuple. Результаты получены из from sys import getsizeof as g; i = [None] * 1000; round((g(list(i)) / g(tuple(i)) - 1) * 100, 2). Создание tuple занимает примерно на 4,17% больше времени, чем создание list (со стандартным отклонением 0,16%). Результаты получены при выполнении from timeit import timeit as t; round((t('tuple(i)', 'i = [None] * 1000') / t('list(i)', 'i = [None] * 1000') - 1) * 100, 2) 30 раз. Мое решение предпочитает пространство скорости, когда необходимость в изменчивости неизвестна.

PatrickT
20 сентября 2021 в 00:17
0

Если бы файл был очень большим, разве это не привело бы к созданию очень большого кортежа? Разве в таких случаях цикл за строкой не будет более эффективным с точки зрения памяти? Спасибо.