Форум сайта python.su
0
Быстродействие хочу добиться, чтобы научиться писать программы с правильным кодом.
Версия той программы которую пишу на python, я уже написал на баше с использованием sed. Поэтому сейчас главный смысл - это обучение!
Офлайн
13
Желание писать “с правильным кодом” ортогонально желанию писать быстрые программы. Вот возьмем тот же readlines или построчное чтение. Если речь идет об обработке файлов большого размера либо большого количества файлов параллельно, то использование readlines категорически противопоказано из-за существенно больших требований к памяти по сравнению с чтением построчно. С точки зрения быстродействия, возможно, вариант с readlines будет быстрее. Какой код будет ‘правильным’ зависит от решаемой задачи.
Отредактировано (Окт. 30, 2011 09:13:21)
Офлайн
0
Вот вариант редактирования конфига без regexp.
Как работает:
1) Читаем все строки в файле, все таки с помощью readlines
2) Вычисляем номер строки, которая начинается начинается с нужного параметра, использую метод строки startswith(), который в каждой строке проверяет первую подстроку, при нахождении такой строки, поиск останавливается.
3) Разбиваем строку на подстроки, разделить “=”
4) У второй подстроки (значение) убираем пробелы, если они есть
5) Сохраняю старое значение (потом пригодится)
6) Изменяю значение и склеиваю обратно все в строку
7) Записываю в файл
#!/usr/bin/python
# edit_rcconf.py
""" Функция редактирования конфигурационного файла rc.conf,
вызывается: rcconf_edit("параметр","значение") """
def rcconf_edit(param, setting):
# Читаем все строки в файле
config = open('rc.conf').readlines()
# Вычисляем номер строки, которая начинается с gateway
num_line = 0 #Номер строки
for line in config:
# Если строка N num_line начинается со слова param
if config[num_line].startswith(param):
break
num_line+=1
# Разбиваем строку на слова
param_sett = config[num_line].split("=")
# Очищаем значение параметра от пробелом и сохраняем в переменную old_setting
old_setting = param_sett[1].strip()
# Заменяем строку "параметр = значение" на новую
param_sett[1] = setting + "\n"
config[num_line] = '='.join(param_sett)
# Записываем новый конфиг в файл
with open('rc.conf', 'w') as config_write:
config_write.writelines(config)
# Вызываем функцию редактрирования rc.conf
rcconf_edit("address", "192.168.1.116")
Офлайн
13
У вас же задача стоит несколько параметров поменять, разве нет? Будете так для каждого параметра делать?
Я бы делал как-нибудь так:
from os import linesep, rename
fname = 'rc.conf'
new_name = '%s.new' % fname
with open(fname) as inf, open(new_name, 'w') as outf:
for line in inf:
for name,value in (("interface", "eth0"), ("address", "192.168.1.100"),
("netmask", "255.255.255.0"), ("gateway", "192.168.1.1")):
if line.startswith(name):
line = "%s=%s%s" % (name, value, linesep)
break
outf.write(line)
rename(new_name, fname)
Отредактировано (Окт. 31, 2011 22:31:46)
Офлайн
32
Edя б тут через словарь сделалfor line in inf:
for name,value in (("interface", "eth0"), ("address", "192.168.1.100"),
("netmask", "255.255.255.0"), ("gateway", "192.168.1.1")):
if line.startswith(name):
line = "%s=%s%s" % (name, value, linesep)
break
outf.write(line)
d = dict([("interface", "eth0"), ("address", "192.168.1.100"), ("netmask", "255.255.255.0"), ("gateway", "192.168.1.1")])
for line in inf:
name = line.split('=')[0].split()
if name in d:
line = "%s=%s%s" % (name, d[name], linesep)
outf.write(line)Отредактировано (Ноя. 1, 2011 07:11:05)
Офлайн
0
Да действительно, для каждого параметра вызывать функцию, не быстро получится. Использую предложенные варианты.
o7412369815963 чем словарь лучше в данной ситуации? Мне кажется словарь больше ресурсов потребляет, чем список ?!
Офлайн
25
Я бы предложил такой вариант:
#/usr/bin/env python
#-*-coding: utf8 -*-
class CfgParser(object):
'''
Dict-like unix config files parser
cfg = CfgParser('/etc/someconfig.cfg')
print cfg['SOMEVAL']
cfg['NEW_STR_VAL'] = 'somestring'
cfg['NEW_INT_VAL'] = 42
print cfg
fd = open('/etc/someconfig.cfg', 'w')
fd.write(repr(cfg))
fd.close()
'''
def __init__(self, config=None):
self._data = list()
if config is not None:
with open(config) as fd:
self.load_lines(fd)
def load_lines(self, iterable):
'''
Parse trough iterable that contains lines
'''
for line in iterable:
strp = line.strip()
if '=' not in strp or \
strp[0] in ('#', ';'):
self._data.append(('_COMMENT_', strp))
else:
name, value = strp.split('=')
self._data.append((name, value))
def _find_key(self, fkey):
'''
Find a key inside self._data
Returns: tuple (index, value)
or (None, None) if key not exists
'''
if fkey != '_COMMENT_':
for idx, key_val in enumerate(self._data):
key, val = key_val
if key == fkey:
return (idx, val.strip('\'\"'))
return (None, None)
def __getitem__(self, key):
_, val = self._find_key(key)
if val is None:
raise IndexError
return val
def __setitem__(self, key, value):
idx, _ = self._find_key(key)
val = ('"%s"' % value) if isinstance(value, basestring) else value
if idx is None:
self._data.append((key, val))
else:
self._data[idx] = (key, val)
def __delitem__(self, key):
idx, _ = self._find_key(key)
if idx is None:
raise IndexError
del self._data[idx]
def __repr__(self):
return '\n'.join(["%s = %s" % (key, val) if key != '_COMMENT_' else val
for key, val in self._data])
if __name__ == '__main__':
import sys
CONFIG_NAME = './rc.conf'
def main(argv=None):
cfg = CfgParser(CONFIG_NAME)
cfg['NEW_STRING'] = 'test'
cfg['NEW_INT'] = 89998
cfg['HARDWARECLOCK'] = 'remote_type'
print cfg
return 0
sys.exit(main(sys.argv))
Офлайн
32
aivsВ данной ситуации любой вариант подойдет т.к. входные данные и обработка смешных размеров.
Да действительно, для каждого параметра вызывать функцию, не быстро получится. Использую предложенные варианты.
o7412369815963 чем словарь лучше в данной ситуации? Мне кажется словарь больше ресурсов потребляет, чем список ?!
Офлайн
25
o7412369815963Это да - но нужно сохранить первоначальную структуру данных.
А если вообще, то получение значения по ключу из словаря в сто-пицот раз быстрее чем поиск перебором.
Офлайн
0
s0rgИменно так!
Это да - но нужно сохранить первоначальную структуру данных.
Офлайн