2010-12-08 16 views
11

私はデータ処理を行うwebappを作っていますので、URLやテキストファイルから文字列を解析することがよくあります。 Pythonの値。Python "safe" eval(文字列をbool/int/float/None/string)

私はevalののより安全なバージョン「のようなもの」である関数を使用する(それは、文字列を読み取ることができない場合、それは文字列のままことを除いて):

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 

...しかし、この私には非常に醜いようです。これを行うクリーナーの方法はありますか?私はold discussionのようなものを見つけましたが、素早く簡単な方法(私が知らないライブラリ関数や賢い1ライナーなど)がないのだろうかと思います。

+0

いいえ、私はあなたが許可したい場合は、これらのタイプのいずれかが、これはおそらくそれを行うための方法だと思います。しかし、それは私にとっては奇妙に思えます。入力がどのようなタイプになるのか分かりませんか?あなたは入力をどうするべきかをどのように知っていますか? –

+1

'string'を' str'(そしてサブクラスでもない)と信用しない限り安全ではありません。そうしないと、悪意ある '__eq__'メソッドを使ってクラスを書くことができます。あなたの文字列がTrueのように見えるかどうか。 – katrielalex

+0

Lennart:たとえば、この種の変換を一般的なCsvToDict関数で使用すると、ExpectKeysToBeInts(CsvToDict( "ints_as_keys.csv"))やExpectValuesToBeFloats(CsvToDict( "float_values.csv"))で使用されます。むしろ私のExpectKeysToBeIntsとExpectValuesToBeFloatsは単純なままで、データ変換を気にする必要はありませんでした。 – Emile

答えて

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

ありがとう! [GuidoのTime Machine](http://dirtsimple.org/2004/12/python-is-not-java.html)が再び襲います!私はastライブラリを掘り下げなければならないでしょう。それは有用なもの(itertools、functools、コレクションなど)を含む可能性が最も高い "汎用ライブラリ"の1つです。 – Emile

+4

私はちょうど私がこれは普通の 'eval'の代わりにこれを使っていたはずです。ああ。 :) –