2016-03-25 3 views
1

У меня есть небольшая проблема с Python. Вот код:Python 3 Заменить строки

f = open('/path/to/file', 'r') 
filedata = f.read() 
f.close() 
postgres = filedata.replace('# DBENGINE=MYSQL', 'DBENGINE=PGSQL') 
dbname = filedata.replace('# DBNAME=DB1', 'DBNAME=DB1') 
dbrwuser = filedata.replace('# DBRWUSER="user1"', 'DBRWUSER="user1"') 
f = open('/path/to/file', 'w') 
f.write(postgres) 
f.write(dbname) 
f.write(dbrwuser) 
f.close() 

Как вы можете видеть, что я пытаюсь прочитать большой файл, и когда я пытаюсь заменить его он просто заменяет «Postgres», и это не делает изменения «DbName, dbrwuser» и т.д. Поэтому я попытался понять это, но не мог этого сделать.

Любая идея или образец?

Спасибо.

+4

Избегайте 'f.read()' для больших файлов. Он считывает весь файл в память. 'with open (filename) как f: для строки в f: ...' обычно лучше, поскольку он читает одну строку за раз. 'string.replace()' возвращает всю строку с первым аргументом, замененным вторым. Это означает, что переменные 'postgres',' dbname' и 'dbrwuser' содержат всю копию всего файла с заменой только указанных строк. То есть 'dbrwuser' все еще имеет' # DBENGINE = MYSQL', а 'postgres' все еще имеет' '# DBRWUSER =" user1 "'. Кроме того, опция 'w' в' f = open() 'будет перезаписывать файл каждый раз. – jDo

+0

@jДа ничего себе, звучит, как я испортил. Должен ли я исправить как «с открытым (имя файла) ....? Каков наилучший способ? –

+1

Я включил комментарии в ответ и добавил некоторые подробности. Не стесняйтесь спрашивать, не кажется ли что-то непонятным. – jDo

ответ

1

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

filedata = filedata.replace('# DBENGINE=MYSQL', 'DBENGINE=PGSQL') 
filedata = filedata.replace('# DBNAME=DB1', 'DBNAME=DB1') 
filedata = filedata.replace('# DBRWUSER="user1"', 'DBRWUSER="user1"') 
... 
f.write(filedata) 
0

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

import re 
repString = {'# DBENGINE=MYSQL': 'DBENGINE=PGSQL', '# DBNAME=DB1': 'DBNAME=DB1', '# DBRWUSER="user1"': 'DBRWUSER="user1"'} 

repString = dict((re.escape(k), v) for k, v in repString.iteritems()) 
pattern = re.compile("|".join(repString.keys())) 
filedata = pattern.sub(lambda m: repString[repString.escape(m.group(0))], filedata) 
f = open('/path/to/file', 'w') 
f.write(filedata) 
f.close() 
0

Несколько предложений и уточнений:

f.read() читает весь файл. Это, вероятно, не очень хорошая идея для больших файлов. Вместо этого используйте

with open(filename, "r") as f: 
    for line in f: 
     # do something with the line 

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

string.replace() возвращает всю строку с первым аргументом, замененным вторым. Поскольку вы создаете новую переменную каждый раз, когда используете replace, изменения применяются только к отдельным переменным. Изменения, внесенные в postgres, не будут существовать в dbname. Вместо этого переопределить переменную filedata для каждого replace, чтобы сохранить изменения и избежать ненужного копирования:

filedata = filedata.replace('# DBENGINE=MYSQL', 'DBENGINE=PGSQL') 
filedata = filedata.replace('# DBNAME=DB1', 'DBNAME=DB1') 
filedata = filedata.replace('# DBRWUSER="user1"', 'DBRWUSER="user1"') 
# at this point, filedata contains all three changes 

При открытии файла для записи с помощью опции w, файл будет перезаписан. Это означает, что файл будет содержать только содержимое, записанное вашей последней записью, f.write(dbrwuser). Вместо этого внесите изменения и напишите один раз или добавьте в файл:

filedata = filedata.replace('# DBENGINE=MYSQL', 'DBENGINE=PGSQL') 
... 
... 

with open('/path/to/file', 'w') as f: 
    f.write(filedata)