Как изменить текстовый файл?

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

Вы можете обратиться к ответу это Алекса Мартелли.

Alok 02.04.2014 08:29
stackoverflow.com/a/4358169/538284
Omid Raha 02.04.2014 22:04

Возможный дубликат Запись в самой верхней строке файла csv в Python

Ani Menon 15.06.2016 08:52

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

Bhargav Rao 15.06.2016 10:49

@BhargavRao Голосование отозвано. Я должен был найти этот дубликат!

Ani Menon 15.06.2016 10:55
Смотрите также:stackoverflow.com/a/1325927/2276527
dreftymac 28.09.2020 22:37
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
191
6
425 309
8

Ответы 8

Зависит от того, чем вы хотите заниматься. Чтобы добавить, вы можете открыть его с помощью "a":

 with open("foo.txt", "a") as f:
     f.write("new line\n")

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

with open("foo.txt", "r+") as f:
     old = f.read() # read everything in the file
     f.seek(0) # rewind
     f.write("new line\n" + old) # write the new line before

Просто небольшое дополнение, чтобы использовать оператор with в Python 2.5, вам нужно добавить «from будущее import with_statement». Кроме того, открытие файлов с помощью оператора with определенно более читабельно и менее подвержено ошибкам, чем закрытие вручную.

Alexander Kojevnikov 24.09.2008 10:48

Вы можете рассмотреть вспомогательную библиотеку fileinput, которая прекрасно обрабатывает грязную процедуру открытия / чтения / изменения / записи / замены при использовании аргумента inline=True. Пример здесь: stackoverflow.com/a/2363893/47390

mikegreenberg 02.02.2012 01:14

Только не забудьте закрыть файл. f.Close()

D.Rosado 02.05.2012 18:35

Я не использую этот стиль, Д. Розадо, но при использовании стиля with не думаю, что вам нужно закрывать его вручную. With отслеживает создаваемый ресурс.

Chris 14.05.2012 21:47

Вам не необходимо вручную закрыть файл. В этом весь смысл использования "with" здесь. (Ну, на самом деле Python делает это, как только файловый объект собирается сборщиком мусора, что в CPython происходит, когда привязанное к нему имя выходит за пределы области видимости ... но другие реализации этого не делают, и CPython может перестать это делать когда-нибудь , поэтому рекомендуется "с")

Jürgen A. Erhard 22.06.2013 15:16

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

Это дело операционной системы, а не Python. Это то же самое на всех языках.

Обычно я читаю из файла, вношу изменения и записываю их в новый файл с именем myfile.txt.tmp или что-то в этом роде. Это лучше, чем чтение всего файла в память, потому что файл может быть слишком большим для этого. После создания временного файла я переименовываю его так же, как исходный файл.

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

Делают ли инструменты unix, такие как awk / sed, что-то подобное в своем коде?

Manish Gill 22.03.2013 23:16

Неправда, что это одно и то же на всех языках. В ActionScript: fileStream.openAsync (имя файла, FileMode.UPDATE); Затем я могу перейти в любое место файла и изменить что угодно.

AndrewBenjamin 11.07.2014 07:58

@AndrewBenjamin Знаете ли вы, какие системные вызовы выполняет ActionScript? Есть ли вероятность, что openAsync прочитает файл и запишет новый после вызова?

AlexLordThorsen 03.12.2014 01:23

@Rawrgulmuffins Я не знаю. Однако я знаю, что он не читает весь файл в память, так как я использовал его для обработки файлов размером в несколько ГБ. Я подозреваю, что это то же самое, что писать с помощью C# streamwriter. Я рассматриваю python как инструмент для быстрого выполнения небольших задач, а не как крупномасштабную разработку и манипулирование файлами.

AndrewBenjamin 27.03.2015 00:48

@AndrewBenjamin, пользователь не спрашивает о поиске в файле и изменении его (каждый язык, который я знаю, может это сделать); он спрашивает о вставке текста, что отличается от простого изменения / перезаписи того, что уже есть в файле. Возможно, в практическом применении это другое, но ничего, что я не могу найти в API ActionScript, указывает на то, что он ведет себя иначе, чем любой другой язык в этом отношении.

eestrada 22.07.2015 17:44

Может я неправильно понял. Думал то же самое - FileStream.writeUTF

AndrewBenjamin 22.07.2015 23:32

Перезапись файла на месте часто выполняется путем сохранения старой копии с измененным именем. Люди из Unix добавляют ~, чтобы пометить старую. Пользователи Windows делают все что угодно - добавляют .bak или .old - или полностью переименовывают файл, или ставят ~ перед именем.

import shutil
shutil.move( afile, afile+"~" )

destination= open( aFile, "w" )
source= open( aFile+"~", "r" )
for line in source:
    destination.write( line )
    if <some condition>:
        destination.write( >some additional line> + "\n" )
source.close()
destination.close()

Вместо shutil можно использовать следующее.

import os
os.rename( aFile, aFile+"~" )

Выглядит хорошо. Хотите знать, лучше ли .readlines (), чем повторять исходный код?

bozdoz 10.04.2013 19:48

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

Jürgen A. Erhard 22.06.2013 15:20

@ S.Lott: os.rename(aFile, aFile + "~") изменит имя исходного файла, а не создаст копию.

Patapoom 12.03.2020 12:39

Модуль Python mmap позволит вам вставить в файл. В следующем примере показано, как это можно сделать в Unix (mmap для Windows может быть другим). Обратите внимание, что это не обрабатывает все условия ошибки, и вы можете повредить или потерять исходный файл. Кроме того, это не будет обрабатывать строки Unicode.

import os
from mmap import mmap

def insert(filename, str, pos):
    if len(str) < 1:
        # nothing to insert
        return

    f = open(filename, 'r+')
    m = mmap(f.fileno(), os.path.getsize(filename))
    origSize = m.size()

    # or this could be an error
    if pos > origSize:
        pos = origSize
    elif pos < 0:
        pos = 0

    m.resize(origSize + len(str))
    m[pos+len(str):] = m[pos:origSize]
    m[pos:pos+len(str)] = str
    m.close()
    f.close()

Это также можно сделать без mmap с файлами, открытыми в режиме 'r +', но это менее удобно и менее эффективно, поскольку вам придется читать и временно сохранять содержимое файла из позиции вставки в EOF, что может быть огромным.

Модуль fileinput стандартной библиотеки Python перезапишет файл на месте, если вы используете параметр inplace = 1:

import sys
import fileinput

# replace all occurrences of 'sit' with 'SIT' and insert a line after the 5th
for i, line in enumerate(fileinput.input('lorem_ipsum.txt', inplace=1)):
    sys.stdout.write(line.replace('sit', 'SIT'))  # replace 'sit' and write
    if i == 4: sys.stdout.write('\n')  # write a blank line after the 5th line

Как это должно работать в python3? Я просто портировал приложение, в котором был такой код, с python на python3, и я просто не мог заставить его работать правильно. Переменная line - это байтовый тип, я попытался расшифровать ее в юникод, а затем изменить, а затем снова закодировать в байты, но это просто не сработало. Это вызвало какое-то исключение, которое я не могу припомнить. Успешно ли люди используют fileinput inplace = 1 в python3?

robru 21.02.2015 08:08

@Robru: вот Код Python 3

jfs 19.12.2016 11:02

Но это не проблема, потому что вы сначала проверили его на несущественном файле, верно?

Paula Livingstone 18.11.2017 16:55

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

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

Опция 1) Прочтите весь файл в память, выполните замену регулярного выражения для всей строки или ее части и замените ее этой строкой и дополнительной строкой. Вам нужно будет убедиться, что «средняя строка» уникальна в файле, или, если у вас есть временные метки в каждой строке, это должно быть довольно надежно.

# open file with r+b (allow write and binary mode)
f = open("file.log", 'r+b')   
# read entire content of file into memory
f_content = f.read()
# basically match middle line and replace it with itself and the extra line
f_content = re.sub(r'(middle line)', r'\nnew line', f_content)
# return pointer to top of file so we can re-write the content with replaced string
f.seek(0)
# clear file content 
f.truncate()
# re-write the content with the updated content
f.write(f_content)
# close file
f.close()

Вариант 2) Найдите среднюю линию и замените ее этой линией и дополнительной линией.

# open file with r+b (allow write and binary mode)
f = open("file.log" , 'r+b')   
# get array of lines
f_content = f.readlines()
# get middle line
middle_line = len(f_content)/2
# overwrite middle line
f_content[middle_line] += "\nnew line"
# return pointer to top of file so we can re-write the content with replaced string
f.seek(0)
# clear file content 
f.truncate()
# re-write the content with the updated content
f.write(''.join(f_content))
# close file
f.close()

Написал небольшой класс, чтобы сделать это чисто.

import tempfile

class FileModifierError(Exception):
    pass

class FileModifier(object):

    def __init__(self, fname):
        self.__write_dict = {}
        self.__filename = fname
        self.__tempfile = tempfile.TemporaryFile()
        with open(fname, 'rb') as fp:
            for line in fp:
                self.__tempfile.write(line)
        self.__tempfile.seek(0)

    def write(self, s, line_number = 'END'):
        if line_number != 'END' and not isinstance(line_number, (int, float)):
            raise FileModifierError("Line number %s is not a valid number" % line_number)
        try:
            self.__write_dict[line_number].append(s)
        except KeyError:
            self.__write_dict[line_number] = [s]

    def writeline(self, s, line_number = 'END'):
        self.write('%s\n' % s, line_number)

    def writelines(self, s, line_number = 'END'):
        for ln in s:
            self.writeline(s, line_number)

    def __popline(self, index, fp):
        try:
            ilines = self.__write_dict.pop(index)
            for line in ilines:
                fp.write(line)
        except KeyError:
            pass

    def close(self):
        self.__exit__(None, None, None)

    def __enter__(self):
        return self

    def __exit__(self, type, value, traceback):
        with open(self.__filename,'w') as fp:
            for index, line in enumerate(self.__tempfile.readlines()):
                self.__popline(index, fp)
                fp.write(line)
            for index in sorted(self.__write_dict):
                for line in self.__write_dict[index]:
                    fp.write(line)
        self.__tempfile.close()

Тогда вы можете использовать это так:

with FileModifier(filename) as fp:
    fp.writeline("String 1", 0)
    fp.writeline("String 2", 20)
    fp.writeline("String 3")  # To write at the end of the file

Это не работает для меня лично, он добавляет текст в файл, но сначала удаляет все!

Bret Hawker 12.01.2019 22:47

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

Mario Krušelj 14.06.2019 12:39

Если вы знаете какой-нибудь unix, вы можете попробовать следующее:

Примечания: $ означает командную строку

Допустим, у вас есть файл my_data.txt с таким содержимым:

$ cat my_data.txt
This is a data file
with all of my data in it.

Затем с помощью модуля os вы можете использовать обычные команды sed.

import os

# Identifiers used are:
my_data_file = "my_data.txt"
command = "sed -i 's/all/none/' my_data.txt"

# Execute the command
os.system(command)

Если вы не знаете о sed, ознакомьтесь с ним, он чрезвычайно полезен.

Это совсем не Pythonic

DarkSuniuM 27.05.2019 04:02

Другие вопросы по теме