Я написал небольшую программу, которая анализирует файлы журналов в диапазоне от нескольких тысяч строк до нескольких сотен тысяч строк.Для этого в моем коде есть функция, которая анализирует каждую строку, ищет ключевые слова и возвращает ключевые слова со связанными значениями.
Эти файлы журналов содержат небольшие разделы.В каждом разделе есть некоторые значения, которые мне интересны и которые я хочу сохранить в виде словаря.
Я упростил приведенный ниже пример, но идея та же.
Моя оригинальная функция выглядела такон вызывается от 100 до 10000 раз за прогон, поэтому вы можете понять, почему я хочу его оптимизировать:
def parse_txt(f):
d = {}
for line in f:
if not line:
pass
elif 'apples' in line:
d['apples'] = True
elif 'bananas' in line:
d['bananas'] = True
elif line.startswith('End of section'):
return d
f = open('fruit.txt','r')
d = parse_txt(f)
print d
Проблема, с которой я сталкиваюсь, состоит в том, что в моей программе много условий,потому что он проверяет много разных вещей и хранит значения для него.И при проверке каждой строки на наличие от 0 до 30 ключевых слов, это быстро замедляется.Я не хочу этого делать, потому что не каждый раз, когда я запускаю программу, меня интересует все.Меня интересуют только 5-6 ключевых слов, но я разбираю каждую строку для примерно 30 ключевых слов.
Чтобы оптимизировать его, я написал следующее, используя exec для строки:
def make_func(args):
func_str = """
def parse_txt(f):
d = {}
for line in f:
if not line:
pass
"""
if 'apples' in args:
func_str += """
elif 'apples' in line:
d['apples'] = True
"""
if 'bananas' in args:
func_str += """
elif 'bananas' in line:
d['bananas'] = True
"""
func_str += """
elif line.startswith('End of section'):
return d"""
print func_str
exec(func_str)
return parse_txt
args = ['apples','bananas']
fun = make_func(args)
f = open('fruit.txt','r')
d = fun(f)
print d
Это решение прекрасно работает, потому что оно ускоряет программу на порядок и относительно просто.В зависимости от аргументов, которые я ввожу, это даст мне первую функцию, но без проверки всего, что мне не нужно.
Например, если я дам ему args=['bananas']
, он не проверит на 'apples'
, и это именно то, что я хочу сделать.
Это сделает его намного более эффективным.
Однако мне не очень нравится это решение, потому что оно не очень читаемо, сложно что-то менять и очень подвержено ошибкам, когда я что-то изменяю.Кроме того, он выглядит немного грязным.
Я ищу альтернативные или лучшие способы сделать это.Я попытался использовать набор функций для вызова каждой строки, и хотя это сработало, оно не дало мне увеличения скорости, которое дает мне мое текущее решение, потому что оно добавляет несколько вызовов функций для каждой строки.Мое текущее решение не имеет этой проблемы, потому что его нужно вызывать только один раз в начале программы.Я читал о проблемах безопасности с exec и eval, но меня это не особо волнует, потому что я единственный, кто его использует.
РЕДАКТИРОВАТЬ: я должен добавить это, для ясности,Я значительно упростил свою функцию.Из ответов я понимаю, что не достаточно ясно это понял.Я не проверяю ключевые слова в согласованном порядке.Иногда мне нужно проверить 2 или 3 ключевых слова в одной строке, иногда только 1. Я также не отношусь к результату одинаково.Например, иногда я извлекаю одно значение из строки, в которой я нахожусь, иногда мне нужно проанализировать следующие 5 строк.