Как мне прочитать каждую строку файла в Python и сохранить каждую строку как элемент в списке?
Я хочу читать файл построчно и добавлять каждую строку в конец списка.
Как мне прочитать каждую строку файла в Python и сохранить каждую строку как элемент в списке?
Я хочу читать файл построчно и добавлять каждую строку в конец списка.
Вот вспомогательный класс 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
.
lines = list(open('filename'))
или
lines = tuple(open('filename'))
или
lines = set(open('filename'))
В случае с set
мы должны помнить, что мы не сохраняем порядок строк и избавляемся от повторяющихся строк.
Поскольку вы не вызываете
.close
для объекта файла и не используете инструкциюwith
, в некоторых реализациях Python файл может не закрываться после чтения, и ваш процесс будет протекать дескриптор открытого файла .В CPython (обычная реализация Python , которую использует большинство людей), это не проблема, так как файловый объект будет немедленно удален из мусора, и это будет закройте файл, но, тем не менее, обычно рекомендуется делать что-то вроде :
with open('filename') as f: lines = list(f)
, чтобы файл был закрыт независимо от того, какую реализацию Python вы используете.
Поскольку вы не вызываете .close
для объекта файла и не используете инструкцию with
, в некоторых реализациях Python файл может не закрываться после чтения, и ваш процесс будет пропускать дескриптор открытого файла. В CPython (обычная реализация Python, которую использует большинство людей) это не проблема, поскольку файловый объект будет немедленно обработан сборщиком мусора, и это закроет файл, но, тем не менее, обычно считается лучшей практикой делать что-то вроде with open('filename') as f: lines = list(f)
чтобы файл был закрыт независимо от того, какую реализацию Python вы используете.
Спасибо за отличный комментарий @MarkAmery! Я очень ценю это.
@simhumileco Почему лучшее (правильное) решение остается последним?
@AMC, потому что во-первых, я хотел показать простейшие способы и для последовательности рассуждений.
Кроме того, я надеюсь, что мой ответ будет кратким и легким для чтения.
В случае, если в документе также есть пустые строки, мне нравится читать содержимое и передавать его через filter
, чтобы предотвратить пустые строковые элементы
with open(myFile, "r") as f:
excludeFileContent = list(filter(None, f.read().splitlines()))
Это непифонично, будьте осторожны.
Я бы попробовал один из нижеперечисленных способов. Файл примера, который я использую, имеет имя 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.']
В чем преимущество второго подхода? Зачем вызывать дополнительную библиотеку, которая добавляет крайние случаи (разделитель и кавычки)?
Для чего нужен аргумент delimiter=' '
?
С помощью 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
.
Представленный в Python 3.4, pathlib
имеет действительно удобный метод чтения текста из файлов, а именно:
from pathlib import Path
p = Path('my_text_file')
lines = p.read_text().splitlines()
(Вызов splitlines
превращает его из строки, содержащей все содержимое файла, в список строк в файле).
pathlib
имеет много удобных вещей. read_text
красиво и лаконично, и вам не нужно беспокоиться об открытии и закрытии файла. Если все, что вам нужно сделать с файлом, это прочитать его за один присест, это хороший выбор.
Мне нравится использовать следующее. Немедленное чтение строк.
contents = []
for line in open(filepath, 'r').readlines():
contents.append(line.strip())
Или используя понимание списка:
contents = [line.strip() for line in open(filepath, 'r').readlines()]
Нет необходимости в readlines()
, что даже приводит к потере памяти. Вы можете просто удалить его, поскольку итерация по (текстовому) файлу дает каждую строку по очереди.
Для открытия (и неявного закрытия) файла следует использовать оператор with
.
Чтобы прочитать файл в списке, вам нужно сделать три вещи:
К счастью, 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()
, но если вы хотите обработать строки перед сохранением их в списке, я бы рекомендовал простое понимание списка. Последний подход - это рекомендуемый подход для открытия файла в Python! Почему же тогда последний? Разве подавляющее большинство людей не взглянут на первые несколько строк ответа, прежде чем двигаться дальше?
@AMC Я не особо задумывался над этим, когда писал ответ. Как вы думаете, я должен поставить это в начале ответа?
Это может быть лучше, да. Я также только что заметил, что вы упоминаете Python 2, так что его тоже можно обновить.
А вопрос изначально был помечен как python-2.x. Возможно, имеет смысл обновить его в более общем плане. Я посмотрю, приду ли я к этому в следующий раз. Спасибо за ваши предложения. Очень признателен!
Чтение и запись текстовых файлов с помощью 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
Более продвинутая запись / чтение файлов
Для вашего приложения может иметь значение следующее:
См. Также: Сравнение форматов сериализации данных
Если вы ищете способ создания файлов конфигурации, вы можете прочитать мою короткую статью Файлы конфигурации в Python .
#!/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
С какой стати вы хотите, чтобы текстовый файл находился в том же каталоге, в котором находится ваш скрипт Python? Просто open(sys.argv[1])
вместо этого, и он будет работать независимо от указанного относительного или абсолютного пути, и ему все равно, где находится ваш скрипт.
Содержимое текстового файла:
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']
требуется ли encoding="utf-8"
?
@ Mausy5043 нет, но когда вы читаете текстовый файл, у вас может быть какой-то странный символ (особенно на итальянском)
read().splitlines()
предоставляется вам Python: это просто readlines()
(что, вероятно, быстрее, поскольку это менее расточительно).
@EricOLebigot из показанных примеров, похоже, что read().splitlines()
и readlines()
не производят одинаковый результат. Вы уверены, что они эквивалентны?
Если вы используете только строки чтения, вам нужно использовать метод полосы, чтобы избавиться от \ n в тексте, поэтому я изменил последние примеры, используя понимание списка, чтобы в обоих случаях вывод был одинаковым. Итак, если вы используете read (). Readlines (), у вас будет «чистый» элемент со строкой и без символа новой строки, в противном случае вы должны сделать то, что вы видите в приведенном выше коде.
Действительно. Обратите внимание, что в приведенном выше коде все strip()
должно быть rstrip("\n")
, или пробелы вокруг строки удаляются. Кроме того, нет смысла делать readlines()
в понимании списка: лучше просто перебирать файл, так как это не тратит время и память на создание промежуточного списка строк.
с open ("Beautify.txt") как file_in: lines = [] для строки в file_in: lines.append (line.replace ('\ n', ''))
Если вы хотите столкнуться с очень большим / огромным файлом и хотите читать быстрее (представьте, что вы участвуете в соревновании по кодированию 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)
что делает процесс (линия)? Я получаю сообщение об ошибке, что такая переменная не определена. Я предполагаю, что что-то нужно импортировать, и я попытался импортировать multiprocessing.Process, но я думаю, что это не так. Не могли бы вы уточнить? Спасибо
process(line)
- это функция, которую необходимо реализовать для обработки данных. например, вместо этой строки, если вы используете print(line)
, он будет печатать каждую строку из lines_buffer.
f.readlines (buffersize) возвращает неизменяемый буфер. если вы хотите напрямую читать в свой буфер, вам нужно использовать функцию readinto (). Я буду намного быстрее.
Просто используйте функции splitlines (). Вот пример.
inp = "file.txt"
data = open(inp)
dat = data.read()
lst = dat.splitlines()
print lst
# print(lst) # for python 3
В выводе будет список строк.
Неэффективность памяти по сравнению с использованием .readlines()
. Это помещает в память сразу две копии содержимого файла (одну как одну огромную строку, другую как список строк).
Но data.read().splitlines()
читать намного легче, и память не всегда вызывает беспокойство по сравнению с простотой чтения кода.
Используйте это:
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()
.
pandas.read_csv()
предназначен для чтения данных CSV , как это здесь уместно?
Вы можете просто сделать следующее, как было предложено:
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 проход. Обычно так работают общие парсеры.
Это было именно то, что мне было нужно - и спасибо за объяснение недостатков. Как новичку в Python, здорово понимать, почему решение есть решение. Ваше здоровье!
в вопросе не говорится о необходимости обрабатывать каждую строку, поэтому этот ответ дает нерелевантную информацию
Подумай еще немного, Кори. Вы действительно когда-нибудь хотите, чтобы ваш компьютер читал каждую строку, ничего не делая с этими строками? Конечно, вы понимаете, что вам всегда нужно так или иначе их обрабатывать.
@DevShark всегда? это просто ложь.
С линиями всегда нужно что-то делать. Это может быть так же просто, как распечатать линии или подсчитать их. Нет никакого смысла в том, чтобы ваш процесс читал строки в памяти, но ничего не делал с ними.
конечно, вы не всегда должны обрабатывать элементы, когда вы читаете их из файла в тот момент, когда вы их читаете ... это ерунда. Возможно, вам нужно создать список элементов, хранящихся в файле, в качестве входных данных для другой функции? Это такая возмутительная идея?
С ними всегда нужно что-то делать. Я думаю, что вы пытаетесь сказать, что вы можете применить функцию ко всем сразу, а не по отдельности. Иногда это действительно так. Но это очень неэффективно с точки зрения памяти и мешает вам читать файлы, если его размер больше, чем ваш Ram. Вот почему типичные парсеры обычно работают так, как я описал.
Хороший подход, но если быть точным: в этом контексте «обработка строк» не изменит их в исходном файле. Вам нужно скопировать их в другой файл, если вам нужно их изменить и сохранить.
@PierreOcinom, это правильно. Учитывая, что файл открывается в режиме только для чтения, вы не можете изменить исходный файл с помощью приведенного выше кода. Чтобы открыть файл для чтения и записи, используйте open('file_path', 'r+')
Я проверил профиль памяти обоих способов, используя описанную здесь процедуру. Использование памяти намного лучше, когда каждая строка считывается из файла и обрабатывается, как предлагает @DevShark. Хранение всех строк в объекте коллекции - это , а не хорошая идея, если память является ограничением или файл большой. Время выполнения одинаково в обоих подходах.
Спасибо за подсчет. Это то, что ожидалось.
@DevShark Загрузка строк в набор для использования в качестве списка фильтров во время выполнения. Все они должны быть загружены в оперативную память, и никакой построчной обработки не требуется.
Мое утверждение было «вам всегда нужно что-то делать с линиями», и ваш пример иллюстрирует это: вы добавляете их в набор. Я думаю, вы утверждаете, что написанный мной код - не единственный способ делать что-то. Это правильно. Чтобы загрузить их все в набор, вам может больше понравиться другой подход - прочитать все строки за один раз.
Вы также можете использовать команду loadtxt в NumPy. Это проверяет меньшее количество условий, чем genfromtxt, поэтому может быть быстрее.
import numpy
data = numpy.loadtxt(filename, delimiter="\n")
Согласно методам 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
Прокомментированная строка в первом примере # my_list = [x.rstrip() for x in f] # remove line breaks
должна быть # my_list = [x.rstrip() for x in my_list] # remove line breaks
.
@oneturkmen нет, он прав. он перебирает строки в файле. Вы были бы правы, если бы строка была после предложения 'with'
Самый простой способ сделать это
Простой способ:
В одной строке это даст:
lines = open('C:/path/file.txt').read().splitlines()
Однако это довольно неэффективный способ, так как при этом в памяти будут храниться 2 версии контента (возможно, это не большая проблема для небольших файлов, но все же). [Спасибо, Марк Амери].
Есть 2 более простых способа:
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')]
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()]
Это плохой подход. Во-первых, позвонить по номеру .read().splitlines()
ни в коем случае не «проще», чем просто позвонить по номеру .readlines()
. Во-вторых, это неэффективно с памятью; вы без нужды сохраняете в памяти сразу две версии содержимого файла (одну строку, возвращаемую .read()
, и список строк, возвращаемых splitlines()
).
@MarkAmery Верно. Спасибо, что подчеркнули это. Я обновил свой ответ.
Чистый и питонический способ чтения строк файла в список
Прежде всего, вы должны сосредоточиться на открытии файла и чтении его содержимого эффективным и питоническим способом. Вот пример того, как я лично НЕ предпочитаю:
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ã.
Вот еще один вариант использования списков в файлах;
lines = [line.rstrip() for line in open('file.txt')]
Этот способ должен быть более эффективным, поскольку большая часть работы выполняется внутри интерпретатора Python.
rstrip()
потенциально удаляет все завершающие пробелы, а не только \n
; используйте .rstrip('\n')
.
Это также не гарантирует, что файл будет закрыт после чтения во всех реализациях Python (хотя в CPython, основной реализации Python, так и будет).
Этот способ должен быть более эффективным, поскольку большая часть работы выполняется внутри интерпретатора Python. Что это означает?
Если вы хотите, чтобы \n
включал:
with open(fname) as f:
content = f.readlines()
Если вы не хотите, чтобы \n
включал:
with open(fname) as f:
content = f.read().splitlines()
отлично, он содержит пустую строку между каждой строкой. '1\n2\n3\n' => [ '1', '', '2', '', '3', '' ]
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)
Вы получите те же результаты.
Если вы хотите прочитать файл из командной строки или из стандартного ввода, вы также можете использовать модуль 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
Другой вариант - numpy.genfromtxt
, например:
import numpy as np
data = np.genfromtxt("yourfile.dat",delimiter="\n")
Это сделает data
массивом NumPy с таким количеством строк, как в вашем файле.
Этот код прочитает весь файл в память и удалит все пробелы (новые строки и пробелы) в конце каждой строки:
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)
В случае, если вы работаете с большими данными, использование readlines()
не очень эффективно, поскольку может привести к MemoryError . В этом случае лучше перебирать файл, используя for line in f:
и работая с каждой переменной line
.
Я проверил профиль памяти разными способами, приведенными в ответах, используя процедуру, упомянутую здесь. Использование памяти намного лучше, когда каждая строка считывается из файла и обрабатывается, как предлагает здесь @DevShark. Хранение всех строк в объекте коллекции - это , а не , что является хорошей идеей, если память является ограничением или файл большой. Время выполнения одинаково в обоих подходах.
Кроме того, .rstrip()
будет работать немного быстрее, если вы удаляете пробелы с концов строк.
Oneliner: with open(filename) as f: content = [i.strip() for i in f.readlines()]
open(filename, encoding='utf-8')
может помочь
@ElderDruid что делать, если кодировка файла не UTF-8
?
Я думаю, что readlines()
устарел.
@ просто напишите [x.strip() for x in f]
, не звоня по номеру readlines()
. Таким образом, вам не нужно создавать дополнительный список.
Из-за rstrip пустая строка в середине файла прервет цикл, поэтому он не будет читать весь файл
См. Ввод и вывод:
with open('filename') as f:
lines = f.readlines()
или с удалением символа новой строки:
with open('filename') as f:
lines = [line.rstrip() for line in f]
Лучше использовать f.read().splitlines()
, который удаляет новые строки
Безопасна ли вторая версия с for line in open(filename)
? То есть файл автоматически закроется?
Лучше читать файл по одной строке за раз, а не читать весь файл в память сразу. Это плохо масштабируется с большими входными файлами. См. Ниже ответ Роберта.
@MFARID «В текстовом режиме при чтении по умолчанию концы строк, зависящие от платформы (\ n в Unix, \ r \ n в Windows) преобразуются только в \ n». (Для Python 3 не менее). Так что rstrip('\r')
не нужен.
lines = [x.rstrip('\n') for x in open('data\hsf.txt','r')]
Если я напишу так, как я могу закрыть файл после прочтения?
Да, в том смысле, о котором здесь говорят другие, хотя использование open
без диспетчера контекста (или какой-либо другой гарантированный способ его закрытия) не является "лучшей практикой", на самом деле это не один из тех случаев - когда объект имеет больше никаких ссылок на него, он будет собран мусором, а файл закроется, что должно произойти немедленно в случае ошибки или нет, когда обработка списка завершится.
@AaronHall «когда у объекта больше нет ссылок на него, он будет собран мусором, а файл закрыт» - это верно для CPython, но не для PyPy. Не все реализации Python немедленно уничтожают объекты, когда на них больше нет ссылок. Таким образом, даже в этом случае уместна передовая практика использования with
с open
.
состояние гонки с Silent Ghost ..;)
Это более явно, чем необходимо, но делает то, что вы хотите.
with open("file.txt") as file_in:
lines = []
for line in file_in:
lines.append(line)
Я предпочитаю этот ответ, поскольку он не требует загрузки всего файла в память (в этом случае он все еще добавляется к array
, но могут быть и другие обстоятельства). Конечно, для больших файлов такой подход может уменьшить проблемы.
Добавление к массиву происходит медленно. Я не могу придумать вариант использования, где это было бы лучшим решением.
@haccks это лучше, потому что он не загружает весь файл в память или есть еще?
Примечание. Это решение не удаляет символы новой строки.
Это решение загружает в память весь файл. Я не знаю, почему люди думают, что это не так.
@andrebrait Он загружает весь файл в строки [] по выбору, но может загружать просто строку за строкой.
Это даст "массив" строк из файла.
lines = tuple(open(filename, 'r'))
open
возвращает файл, который можно повторять. Когда вы перебираете файл, вы получаете строки из этого файла. tuple
может взять итератор и создать для вас экземпляр кортежа из итератора, который вы ему предоставили. lines
- кортеж, созданный из строк файла.
Это лучший ответ, если вы хотите, чтобы там были символы новой строки. Есть ли способ изменить его, чтобы убрать их, не нарушая красивой простоты этой версии?
@MarshallFarrier Попробуйте вместо этого lines = open(filename).read().split('\n')
.
он закрывает файл?
@Vanuan Поскольку после выполнения строки не остается ссылки на файл, деструктор должен автоматически закрыть файл.
@NoctisSkytower Я считаю, что lines = open(filename).read().splitlines()
немного чище, и я считаю, что он также лучше обрабатывает окончания строк DOS.
@ dal102 Да, я согласен с вами и желаю, чтобы я узнал о методе splitlines
раньше. Однако обратите внимание, что аргумент newline
функции open
равен None
, поэтому включен универсальный режим новой строки и в этом случае допустимо разделение на '\n'
. Однако особенно интересно то, что существует метод bytes.splitlines
. Это дает возможность имитировать универсальный режим новой строки при открытии файла в двоичном режиме. На самом деле вам не нужно открывать файл в текстовом режиме, чтобы легко разделить данные файла по границам строк и избежать импорта модуля re
.
Это элегантно (за исключением того, что в самом ответе стоит отметить, что завершающий \n
сохраняется в каждом элементе), но мне любопытно, почему вы выбрали tuple()
вместо list()
. Судя по моим неофициальным тестам, list()
работает немного лучше (вероятно, не имеет большого значения). list()
, в отличие от tuple()
, вернет изменяемую последовательность (которая может быть, а может и не быть желательной).
@ 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 раз. Мое решение предпочитает пространство скорости, когда необходимость в изменчивости неизвестна.
Если бы файл был очень большим, разве это не привело бы к созданию очень большого кортежа? Разве в таких случаях цикл за строкой не будет более эффективным с точки зрения памяти? Спасибо.
Действительно ли
lines = FileIO.lines(path)
проще, чемwith open(path) as f: lines = f.readlines()
, чтобы оправдать существование этого помощника? Вы экономите примерно 17 символов на звонок. (И в большинстве случаев из соображений производительности и памяти вы захотите перебрать файловый объект напрямую вместо того, чтобы читать его строки в списке, так что вы даже не захотите часто использовать это!) Я часто фанат создания небольших служебных функций, но мне кажется, что это просто напрасное создание нового способа написать что-то, что и без того короткое и простое с помощью стандартной библиотеки дает нам.В дополнение к тому, что сказал @MarkAmery, зачем использовать для этого класс?