2009-09-21 1 views
2

Я пытаюсь написать очень простую утилиту Python для личного использования, которая подсчитывает количество строк в текстовом файле, для которого предикат, указанный в командной строке, является истинным. Вот код:Python Eval: Что не так с этим кодом?

import sys 

pred = sys.argv[2] 
if sys.argv[1] == "stdin" : 
    handle = sys.stdin 
else : 
    handle = open(sys.argv[1]) 
result = 0 
for line in handle : 
    eval('result += 1 if ' + pred + ' else 0') 
print result 

Когда я запускаю его с помощью python count.py myFile.txt "int(line) == 0", я получаю следующее сообщение об ошибке:

File "c:/pycode/count.py", line 10, in <module> 
    eval('toAdd = 1 if ' + pred + ' else 0') 
    File "<string>", line 1 
    toAdd = 1 if int(line) == 0 else 0 

Это выглядит вполне действительный код Python для меня (хотя я никогда не использовал Eval Python перед , поэтому я не знаю, каковы его причуды, если таковые имеются). Скажите, пожалуйста, как я могу это исправить, чтобы он работал.

ответ

3
#!/usr/bin/env python 
import fileinput, sys 

pred = eval('lambda line: ' + sys.argv[1]) 
print sum(1 for line in fileinput.input(sys.argv[2:]) if pred(line)) 

Использование: pywc.py predicate [FILE]...
Печать количество строк, которые удовлетворяют predicate для данного FILE (ов).
Без FILE, или когда FILE -, прочитайте стандартный ввод.

+0

Это отличное, отличное улучшение по сравнению с другими версиями в простоте и эффективности. –

+1

Спасибо. Я думаю, что это намного быстрее, чем другие версии, потому что интерпретатор анализирует и компилирует предикат O (1) вместо O (N) раз. – dsimcha

11

Попробуйте использовать exec вместо eval. Разница между 2 объясняется here

+0

Спасибо. Простой вопрос, простой ответ. – dsimcha

+0

приветствуются! – ennuikiller

2

Функция python eval() вычисляет выражения, а не инструкции. Попробуйте заменить строку Eval() с:

result += eval(pred + " else 0") 
+1

'eval ('int (line) == 0 else 0')' производит 'SyntaxError'. – jfs

5

попробовать:

for line in handle: 
    result += 1 if eval(pred) else 0 
0

Действительно, вы ищете функции компиляции:

>> a = compile("toAdd = 1 if int('0') == 0 else 0", 'tmp2.py', 'exec') 
>>> eval(a) 
>>> toAdd 
1 

Eval предназначен только для выражений .. компилировать во время компиляции последовательности инструкций в кодовый блок, который затем может быть оценен.

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

  • Нет связанных вопросов^_^