2011-06-30 7 views
10

私は、メッセージストリームを監視して操作できるGUIアプリケーションを作成しています。私は、ユーザーにこの機能の一部をスクリプトにさせる簡単な手段を作成しようとしています。候補を探しています。私はElementTreeのを使用して計画して解析するためのPythonで簡単なスクリプト言語を作成する

<if> 
    <condition> 
     <recv> 
     <MesgTypeA/> 
     </recv> 
    </condition> 
    <loop count=10> 
     <send> 
     <MesgTypeB> 
      <param1>12</param1> 
      <param2>52</param2> 
     </MesgTypeB> 
     </send> 
    </loop> 
</if> 

をし、単にコードのうち、状態を構築:当初、私はそれが自然に埋め込まれたコードの世話をすることができますので、XMLを使用していました。 XMLの作成と読み込みは、特にスクリプトの作者が何らかの経験を持つとは想定できないので、最も簡単なことではありません。誰かがPythonで読み書きして処理するのが簡単な選択肢があるのか​​どうか疑問に思っていました。私はJSONを調べましたが、スクリプトであるため注文が重要です。

誰でも可能な代替案を提案できますか?

ありがとうございました。

答えて

16

Pythonについて教えてくださいitself?例えば

>>> import code 
>>> def host_func(): 
...  print("Hello old chap!") 
... 
>>> c = code.compile_command("print(\"Script says hello!\"); host_func()") 
>>> exec(c) 
Script says hello! 
Hello old chap! 

execみましょうあなたがホスト環境から使用すると、2つのオプションのパラメータlocalsglobalsを通じて公開するかについて明確にします。

この例では、スクリプトがどのグローバルにアクセスできるかについて明示しています。ここで変数を "作成"するか、既存の関数に別の名前を付けることができます。関数とデータを指す辞書です。

与え、既存のものに戻って指して、二つの機能を含むグローバルでこれを呼び出す
>>> import code 
>>> def secret(): 
...  print("What?! I don't even... get out of here.") 
... 
>>> def public(): 
...  print("Hello stranger.") 
... 
>>> c = code.compile_command("secret(); public()") 

:私はsecretを省略する場合

>>> exec(c, {"secret": secret, "public": public}) 
What?! I don't even... get out of here. 
Hello stranger. 

を今、スクリプトはもはやそれを見つけることはできません。

>>> exec(c, {"public": public}) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<input>", line 1, in <module> 
NameError: name 'secret' is not defined 

は、ここで私はすべて一緒 secretを再定義:コメントで言及

>>> exec(c, {"public": public, "secret":lambda: print("Haha! Doppelganger.")}) 
Haha! Doppelganger. 
Hello stranger. 

lazyrなどのセキュリティ上の懸念があります。上記の例は、スクリプトが望むように動作するようにします。場合によってはこれは受け入れられません。

1がそれを阻止するために行うことができますいくつかのものがあります:

  • 中性__builtins__、唯一の「ホワイトリストされた」組み込み関数が可能。
  • モジュールを読み込みにくくします。

たとえば、importステートメントをボークする方法は次のとおりです(Py2の場合)。*組み込みコマンド__builtins__)である。このことから

>>> import builtins 
>>> def no_import(*args, **kwargs): 
...  raise ImportError("I cannot let you do that, Dave.") 
... 
>>> builtins.__import__ = no_import 
>>> import os 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 2, in no_import 
ImportError: I cannot let you do that, Dave. 

は、我々はグローバルパラメータでbuiltins私たち自身を渡すことができるということになる。それは後に起こる

>>> import code 
>>> evil_code = "import os; import stat; os.chmod(\"passwords.txt\", stat.S_IROT 
H);" 
>>> compiled = code.compile_command(evil_code) 
>>> def no_import(*args, **kwargs): 
... raise ImportError("I cannot let you do that, Dave.") 
... 
>>> exec(compiled, {"__builtins__": {"__import__": no_import}}) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<input>", line 1, in <module> 
    File "<stdin>", line 2, in no_import 
ImportError: I cannot let you do that, Dave. 

注意すべき点は、しかし、これはBORKするすべての輸入品。ホワイトリストに登録されたモジュールをインポートできるバージョンに置き換える方が良いかもしれません。

最後に、これが完全にあなたを守るかどうかはわかりません。いくつかの狡猾な人はそれをうまく回避するかもしれません。しかし、最も露骨な違反は、少なくとも落胆する必要があります。

+0

+1あなたは5000の評判マイルストーンを過ぎてしまいます。多分あなたはセキュリティ上の懸念について何か言及するべきでしょうか? –

+0

@lazyr:ああ、ありがとうございます:D ...私はケーキで祝いましょう。はい、私はそれについて考えていました。私はそれについてのポイントを追加することができます。 – Skurmedel

+0

テキストの壁が+400のダメージを与えます。 – Skurmedel

3

構文解析が簡単であるため、PythonまたはLispである可能性があります。

5

pyparsingで独自のスクリプト言語の構文を定義できます。