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






Зависит от того, чем вы хотите заниматься. Чтобы добавить, вы можете открыть его с помощью "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 определенно более читабельно и менее подвержено ошибкам, чем закрытие вручную.
Вы можете рассмотреть вспомогательную библиотеку fileinput, которая прекрасно обрабатывает грязную процедуру открытия / чтения / изменения / записи / замены при использовании аргумента inline=True. Пример здесь: stackoverflow.com/a/2363893/47390
Только не забудьте закрыть файл. f.Close()
Я не использую этот стиль, Д. Розадо, но при использовании стиля with не думаю, что вам нужно закрывать его вручную. With отслеживает создаваемый ресурс.
Вам не необходимо вручную закрыть файл. В этом весь смысл использования "with" здесь. (Ну, на самом деле Python делает это, как только файловый объект собирается сборщиком мусора, что в CPython происходит, когда привязанное к нему имя выходит за пределы области видимости ... но другие реализации этого не делают, и CPython может перестать это делать когда-нибудь , поэтому рекомендуется "с")
К сожалению, нет возможности вставить в середину файла, не перезаписав его. Как указывалось на предыдущих плакатах, вы можете добавить к файлу или перезаписать его часть, используя поиск, но если вы хотите добавить что-то в начале или в середине, вам придется его переписать.
Это дело операционной системы, а не Python. Это то же самое на всех языках.
Обычно я читаю из файла, вношу изменения и записываю их в новый файл с именем myfile.txt.tmp или что-то в этом роде. Это лучше, чем чтение всего файла в память, потому что файл может быть слишком большим для этого. После создания временного файла я переименовываю его так же, как исходный файл.
Это хороший и безопасный способ сделать это, потому что, если запись файла завершится сбоем или прервется по какой-либо причине, у вас все еще будет нетронутый исходный файл.
Делают ли инструменты unix, такие как awk / sed, что-то подобное в своем коде?
Неправда, что это одно и то же на всех языках. В ActionScript: fileStream.openAsync (имя файла, FileMode.UPDATE); Затем я могу перейти в любое место файла и изменить что угодно.
@AndrewBenjamin Знаете ли вы, какие системные вызовы выполняет ActionScript? Есть ли вероятность, что openAsync прочитает файл и запишет новый после вызова?
@Rawrgulmuffins Я не знаю. Однако я знаю, что он не читает весь файл в память, так как я использовал его для обработки файлов размером в несколько ГБ. Я подозреваю, что это то же самое, что писать с помощью C# streamwriter. Я рассматриваю python как инструмент для быстрого выполнения небольших задач, а не как крупномасштабную разработку и манипулирование файлами.
@AndrewBenjamin, пользователь не спрашивает о поиске в файле и изменении его (каждый язык, который я знаю, может это сделать); он спрашивает о вставке текста, что отличается от простого изменения / перезаписи того, что уже есть в файле. Возможно, в практическом применении это другое, но ничего, что я не могу найти в API ActionScript, указывает на то, что он ведет себя иначе, чем любой другой язык в этом отношении.
Может я неправильно понял. Думал то же самое - FileStream.writeUTF
Перезапись файла на месте часто выполняется путем сохранения старой копии с измененным именем. Люди из 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: итерация лучше, так как строки чтения читают весь файл. Не подходит для больших файлов. Конечно, это предполагает, что вы можете вносить изменения таким локализованным способом. Иногда вы не можете, или ваш код становится намного сложнее.
@ S.Lott: os.rename(aFile, aFile + "~") изменит имя исходного файла, а не создаст копию.
Модуль 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: вот Код Python 3
Но это не проблема, потому что вы сначала проверили его на несущественном файле, верно?
Как упоминал Адам, вы должны принять во внимание ограничения вашей системы, прежде чем вы сможете решить, достаточно ли у вас памяти, чтобы прочитать все это в памяти, заменить ее части и перезаписать.
Если вы имеете дело с небольшим файлом или у вас нет проблем с памятью, это может помочь:
Опция 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
Это не работает для меня лично, он добавляет текст в файл, но сначала удаляет все!
Действительно, это совсем не работает. Жалко, потому что это казалось хорошей идеей.
Если вы знаете какой-нибудь 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
Вы можете обратиться к ответу это Алекса Мартелли.