2010-12-08 17 views
11

Ich mache eine Webapp, die einige Daten verarbeitet, so dass ich häufig Strings (von einer URL oder einer Textdatei) in Parsing finde Python-WertePython "sicher" eval (string zu bool/int/float/Keine/string)

Ich verwende eine Funktion, die „Art“ eine sicherere Version von eval ist (außer, dass, wenn es nicht die Zeichenfolge lesen kann, bleibt es eine Zeichenfolge):

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 

... aber diese scheint mir sehr hässlich. Gibt es einen saubereren Weg, dies zu tun? Ich fand eine old discussion os so etwas, aber ich frage mich, ob es nicht eine schnelle und einfache Möglichkeit (wie eine Bibliothek Funktion, die ich nicht kenne, oder eine clevere Einzeiler?).

+0

Nein, ich glaube, dass, wenn Sie dies jede dieser Arten ermöglichen wollen, ist wahrscheinlich die Art und Weise, es zu tun. Aber mir kommt es seltsam vor. Weißt du nicht, welchen Typ die Eingabe sein wird? Woher weißt du, was mit der Eingabe zu tun ist? –

+1

Dies ist nicht sicher, es sei denn, du vertraust darauf, dass 'string' eine' str' (und keine Unterklasse) ist - andernfalls könnte ein Übeltäter eine Klasse mit einer bösartigen '__eq__' Methode schreiben, die beim Test aufgerufen würde ob Ihre Zeichenfolge wie "True" aussieht. – katrielalex

+0

Lennart: zum Beispiel kann ich diese Art von Konvertierung in einer generischen CsvToDict-Funktion verwenden, die dann in ExpectKeysToBeInts (CsvToDict ("ints_as_keys.csv")) und in ExpectValuesToBeFloats (CsvToDict ("float_values.csv")) verwendet wird - Ich würde eher meine ExpectKeysToBeInts und ExpectValuesToBeFloats bleiben einfach und musste nicht um Datenkonvertierung kümmern. – Emile

Antwort

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

Danke! [Guido's Time Machine] (http://dirtsimple.org/2004/12/python-is-not-java.html) schlägt wieder! Ich muss durch die ast-Bibliothek graben, es ist eine dieser "Allzweck" -Bibliotheken, die am wahrscheinlichsten nützliche Dinge enthalten (wie itertools, functools, Sammlungen ...) – Emile

+4

Ich habe gerade gemerkt, wie viele böse dreckige Hacks ich habe erstellt in der Vergangenheit, die diese anstelle von einfachen 'eval' verwendet haben sollte. Autsch. :) –