2010-12-08 31 views
11

Je fais une webapp qui fait un peu de traitement de données, donc je me trouve souvent l'analyse des chaînes (à partir d'une URL ou un fichier texte) dans Valeurs PythonEval "sûr" eval (chaîne à bool/int/float/None/chaîne)

J'utilise une fonction qui est « une sorte de » une version plus sûre de eval (sauf que si elle ne peut pas lire la chaîne, il reste une chaîne):

def str_to_value(string): 
    for atom in (True, False, None): 
     if str(atom) == string: 
      return atom 
    else: 
     try: 
      return int(string) 
     except ValueError: 
      try: 
       return float(string) 
      except ValueError: 
       return string 

... Cependant, cette me semble très moche. Y a-t-il une façon plus propre de faire cela? J'ai trouvé un old discussion quelque chose comme ça, mais je me demande s'il n'y a pas un moyen simple et rapide (comme une fonction de bibliothèque que je ne connais pas, ou un liner intelligent?).

+0

Non, je pense que si vous voulez autoriser l'un de ces types c'est probablement la façon de le faire. Mais cela me semble étrange. Vous ne savez pas quel type sera l'entrée? Comment saurez-vous quoi faire avec l'entrée? –

+1

Ce n'est pas sûr sauf si vous faites confiance 'string' pour être' str' (et pas une sous-classe, non plus) - sinon, un malfaiteur pourrait écrire une classe avec une méthode '__eq__' malveillante qui serait appelée quand vous testiez si votre chaîne ressemble à True. – katrielalex

+0

Lennart: par exemple, je peux utiliser ce type de conversion dans une fonction CsvToDict générique, qui sera ensuite utilisée dans ExpectKeysToBeInts (CsvToDict ("ints_as_keys.csv")) et dans ExpectValuesToBeFloats (CsvToDict ("float_values.csv")) - Je préférerais que mes ExpectKeysToBeInts et ExpectValuesToBeFloats restent simples et n'aient pas à se soucier de la conversion de données. – Emile

Répondre

27

ast.literal_eval()

>>> ast.literal_eval('{False: (1, 0x2), True: [3.14, 04, 0b101], None: ("6", u"7", r\'8\')}') 
{False: (1, 2), True: [3.1400000000000001, 4, 5], None: ('6', u'7', '8')} 
+1

Merci! [Guido's Time Machine] (http://dirtsimple.org/2004/12/python-is-not-java.html) frappe à nouveau! Je vais devoir fouiller dans la bibliothèque ast, c'est une de ces bibliothèques "génériques" qui sont les plus susceptibles de contenir des choses utiles (comme itertools, functools, collections ...) – Emile

+4

Je viens de me rendre compte combien de mauvais hacks sales j'ai créé dans le passé qui aurait dû utiliser ceci au lieu de plain 'eval'. Aie. :) –