2013-03-15 5 views
3

У меня есть несколько кодов питона, которые управляют большими файлами. В некоторых из них я выполняю операции между столбцами или выбираю их содержимое. Поскольку входные файлы могут иметь разные структуры, операции предоставляются в командной строке с синтаксисом, подобным этому c3 + c5 -1 или (c3<4) & (c5>4) (или комбинациями). c4 интерпретируется как четвертый столбец входного файла.Выполнять операции, заданные пользователем с (out) eval()

Мои файлы выглядеть примерно так ('input_file.txt'):

21.3 4321.34 34.12 4 343.3 2 324 
34.34 67.56  764.45 2 54.768 6 45265 
986.96 87.98  234.09 1 54.456 3 5262 
[...] 

Давайте предположим, что я хочу подвести колонку 4 с колонки 5 и вычесть 1.
я бы

import re 
import numpy as np 

operation = "c3 + c5 -1" #in reality given from command line 
pattern = re.compile(r"c(\d+?)") # compile the regex that matches the column number 
# get the actual expression to evaluate 
to_evaluate = pattern.sub("ifile[:,\\1]", operation) 
#to_evaluate is: "ifile[:,3] + ifile[:,5] -1" 

ifile = np.loadtxt('input_file.txt') 
result = eval(to_evaluate) #evaluate the operation required 
print(result) 
# do the rest 

Выход

[5, 7, 3, ...]

Я придумал эту реализацию, потому что:

  1. это легко писать и изменять, если я хочу изменить метод для чтения файлов (на данный момент я могу решить, использовать numpy или pandas) или если я хочу добавить операции
  2. дает мне много свободы на то, что я могу сделать. Таким же образом можно обрабатывать c3 + c5 -1, (c3<4) & (c5>4) или (c2+c4)>0.
  3. У меня такая же подпись во всех моих кодов: это менее вероятно, делать ошибки

Я знаю, что eval может быть небезопасно (хотя сейчас я единственный пользователь из этих кодов) и может быть медленнее, чем соответствующий код, но я не мог придумать лучшего способа.

Кому-нибудь известно о более эффективных/безопасных способах осуществления таких операций?

дополнительные изменения: если это имеет значение, я бегу питона 2,7

ответ

2

Вы можете сделать более безопасным Eval

def safe_eval(eval_str, variable_dict = None): 
    '''welll... mostly safe: 
     http://lybniz2.sourceforge.net/safeeval.html 
    ''' 
    if variable_dict == None: 
     variable_dict = {} 
    return eval(eval_str, {"__builtins__" : None}, variable_dict) 

Хотя он никогда не будет делать это совершенно безопасно от кого-то, кто знает питон очень хорошо (см. пример http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html)

Ваше приложение меня сбивает с толку, поэтому я не уверен, насколько я могу вам помочь!


Я не уверен, если это поможет решить, что вы делаете, но одна вещь, которую вы можете сделать, это собрать все функции в модуле в словаре.

Таким образом, вы можете скомпилировать функции, которые вы хотите использовать через что-то вроде:

module_dict = {} 
for n in dir(module): 
module_dict[n] = eval('module.'+n) 

(Я считаю, что эта функция является стандартной в Python 3. т.е. все модули модуль dicionaries может быть доступен.) Это ставит все вызовы функций в словарной форме, что ускоряет вызовы. Он также решает проблемы безопасности eval.

Если вы пытаетесь использовать операции типа «+» или «=», вы можете получить их вызовы функций из объекта. добавить и объект. eq. Вы можете сохранить эти вызовы в свой синтаксис строк.

Не уверен, что это помогает.

+0

спасибо за функцию и ссылку, очень интересно. Если вы можете сказать мне, что вы считаете запутанным, я могу попытаться отредактировать вопрос, чтобы сделать его более ясным. –

+0

Я просто не понимаю эти файловые операции. Хм ... У меня есть идея. См. Выше в ближайшее время. –

+0

поможет, если я добавлю несколько строк макетного файла и ответ, который я ожидаю? –

Смежные вопросы