Перезапись файлов Python после разбора - PullRequest
0 голосов
/ 19 мая 2011

Я новичок в Python, и мне нужно выполнить упражнение по синтаксическому анализу.Я получил файл, и мне нужно проанализировать его (только заголовки), но после этого процесса мне нужно сохранить файл в том же формате, с тем же расширением и в том же месте на диске, но только с учетом различийновые заголовки ..

Я попробовал этот код ...

for line in open ('/home/name/db/str/dir/numbers/str.phy'):
    if line.startswith('ENS'):
        linepars = re.sub ('ENS([A-Z]+)0+([0-9]{6})','\\1\\2',line)
        print linepars

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

Ответы [ 5 ]

4 голосов
/ 19 мая 2011

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

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

fr = open('/home/name/db/str/dir/numbers/str.phy')
fw = open('/home/name/db/str/dir/numbers/str.phy.parsed', 'w') # Name this whatever makes sense

for line in fr:
    if line.startswith('ENS'):
        linepars = re.sub ('ENS([A-Z]+)0+([0-9]{6})','\\1\\2',line)
        fw.write(linepars)
    else:
        fw.write(line)

fw.close()
fr.close()

РЕДАКТИРОВАТЬ: обратите внимание, что это не использует readlines(), поэтому его более эффективно использовать память.Он также хранит не все выходные строки, а только по одной за раз, записывая их в файл немедленно.

Точно так же вы можете использовать оператор with для входного файла, чтобы избежать необходимостизакройте его (Python 2.5 +):

fw = open('/home/name/db/str/dir/numbers/str.phy.parsed', 'w') # Name this whatever makes sense

with open('/home/name/db/str/dir/numbers/str.phy') as fr:
    for line in fr:
        if line.startswith('ENS'):
            linepars = re.sub ('ENS([A-Z]+)0+([0-9]{6})','\\1\\2',line)
            fw.write(linepars)
        else:
             fw.write(line)

fw.close()

PS Добро пожаловать: -)

2 голосов
/ 19 мая 2011

Как говорят здесь другие, вы хотите открыть файл и использовать метод .write() объекта этого файла.

Наилучшим подходом будет открыть дополнительный файл для записи:

import os

current_cfg = open(...)
parsed_cfg  = open(..., 'w')
for line in current_cfg:
    new_line = parse(line)
    print new_line
    parsed.cfg.write(new_line + '\n')
current_cfg.close()
parsed_cfg.close()

os.rename(....) # Rename old file to backup name
os.rename(....) # Rename new file into place

Кроме того, я бы посоветовал взглянуть на модуль tempfile и использовать один из его методов либо для присвоения имени новому файлу, либо для его открытия / создания.Лично я предпочел бы поместить новый файл в тот же каталог, что и существующий файл, чтобы гарантировать, что os.rename будет работать атомарно (указанный файл конфигурации будет гарантированно указывать либо на старый файл, либо на новый файл; ни в коем случае не будетэто указывает на частично записанный / скопированный файл).

0 голосов
/ 26 декабря 2011

Следующий код выполняет работу.
Я имею в виду, что он перезаписывает файл на себя; это то, что попросил ОП. Это возможно, потому что преобразования удаляют только символы, поэтому записываемый указатель файла fo всегда находится за указателем файла fi , который читает.

import re

regx = re.compile('\AENS([A-Z]+)0+([0-9]{6})')

with open('bomo.phy','rb+') as fi, open('bomo.phy','rb+') as fo:
    fo.writelines(regx.sub('\\1\\2',line) for line in fi)

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

0 голосов
/ 19 мая 2011

(sidenote: Конечно, если вы работаете с большими файлами, вы должны знать, что требуемый уровень оптимизации может зависеть от вашей ситуации. Python по своей природе очень лениво оценивается. Следующее решение не является хорошимвыбор, если вы анализируете большие файлы, такие как дампы базы данных или журналы, но несколько хитростей, таких как вложение предложений with и использование ленивых генераторов или построчный алгоритм, может позволить поведение O (1) -памяти.)

targetFile = '/home/name/db/str/dir/numbers/str.phy'

def replaceIfHeader(line):
    if line.startswith('ENS'):
        return re.sub('ENS([A-Z]+)0+([0-9]{6})','\\1\\2',line)
    else:
        return line

with open(targetFile, 'r') as f:
    newText = '\n'.join(replaceIfHeader(line) for line in f)

try:
    # make backup of targetFile
    with open(targetFile, 'w') as f:
        f.write(newText)
except:
    # error encountered, do something to inform user where backup of targetFile is

edit: спасибо Джеффу за предложение

0 голосов
/ 19 мая 2011
newlines = []
for line in open ('/home/name/db/str/dir/numbers/str.phy').readlines():
    if line.startswith('ENS'):
        linepars = re.sub ('ENS([A-Z]+)0+([0-9]{6})','\\1\\2',line)
        newlines.append( linepars )
open ('/home/name/db/str/dir/numbers/str.phy', 'w').write('\n'.join(newlines))
...