2009-09-21 6 views
2

J'essaie d'écrire un utilitaire Python très simple pour un usage personnel qui compte le nombre de lignes dans un fichier texte pour lequel un prédicat spécifié à la ligne de commande est vrai. Voici le code:Python Eval: Quel est le problème avec ce code?

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 

Quand je lance à l'aide python count.py myFile.txt "int(line) == 0", je reçois l'erreur suivante:

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 

Cela ressemble à du code Python parfaitement valide pour moi (même si je ne l'ai jamais utilisé le eval de Python avant , donc je ne sais pas quelles sont ses bizarreries, le cas échéant). S'il vous plaît dites-moi comment je peux résoudre ce problème pour le faire fonctionner.

Répondre

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)) 

Utilisation: pywc.py predicate [FILE]...
Numéro d'impression des lignes qui satisfont predicate pour FILE donné (s).
Sans FILE, ou lorsque FICHIER est -, lire l'entrée standard.

+0

Ceci est excellent, une grande amélioration par rapport aux autres versions en termes de simplicité et d'efficacité. –

+1

Merci. C'est beaucoup plus rapide que les autres versions, je suppose que l'interpréteur analyse et compile le prédicat O (1) au lieu de O (N) fois. – dsimcha

11

Essayez d'utiliser exec au lieu d'eval. La différence entre les 2 est expliquée here

+0

Merci. Question simple, réponse simple. – dsimcha

+0

vous êtes les bienvenus! – ennuikiller

2

La fonction python eval() évalue les expressions, pas les instructions. Essayez de remplacer le eval() en ligne avec:

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

'eval ('int (line) == 0 else 0')' produit 'SyntaxError'. – jfs

5

essayer:

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

Vraiment, vous êtes à la recherche de la fonction de compilation:

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

eval est destiné uniquement aux expressions .. compiler en compilant une séquence d'instructions dans un codeblock qui peut ensuite être évalué.

Questions connexes