atsukanrockのブログ

Microsoft系技術を中心にぼちぼち更新します

IronPythonでプログラミング可能なCONFIGファイルを実装する

はじめに

IronPythonを使えば、CONFIGファイルで自由にプログラミング可能なアプリケーションを、実装できる。本エントリでは、その方法を簡単に紹介する。

完成したCONFIGファイルのイメージ

「'hoge' + 'fuga'」とある部分が、Pythonのコードだ。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
            <section name="IronPythonSample.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
        </sectionGroup>
    </configSections>
    <applicationSettings>
        <IronPythonSample.Properties.Settings>
            <setting name="PythonCode" serializeAs="String">
                <value>'hoge' + 'fuga'</value>
            </setting>
        </IronPythonSample.Properties.Settings>
    </applicationSettings>
</configuration>

IronPythonとは

インターネット上で簡単に調べられるので、ここでは詳細を述べないが、キーワードを挙げる。

DLRとは

IronPythonとは」で触れたDLRとは何か。これもインターネット上で簡単に調べられるので、ここでは詳細を述べないが、キーワードを挙げる。

つまり、次のようなイメージだ*2

IronPython IronRuby (様々な実装)
DLR
CLR

前置きはここまでにして、実際に実装していく。

IronPythonをインストール

IronPythonDownloadsページに行き、「IronPython <バージョン> for .NET <.NETのバージョン>.msi」をダウンロード。あとはインストールでOKだ。ここでは、「IronPython 2.6.1 for .NET 2.0 SP1.msi」をインストールしたものとする。

ホストアプリケーションを作成

IronPythonをホストする.NETアプリケーションを作成する。.NETからIronPythonを使うのに必要なのは、IronPythonアセンブリへの参照の追加だけだ。IronPythonをインストールしたディレクトリ直下に、いくつかのDLLファイルがあるので、それらのうち必要なものを、アプリケーションから参照する。

余談だが、どのDLLファイルが必要なのかが、私には分からない。インターネットで調べてみると、情報があるにはあったのだが、確認が持てなかった。と言うのも、どうやらIronPythonのバージョンによってDLLファイルの構成が違うようで、使おうとしているバージョンではどうなのかが、はっきりしないのだ。そのため今回は、上記ディレクトリ内に7つもあるDLLファイルを、全て参照した。

CONFIGファイルを作成

文字列の値を取る設定項目をCONFIGファイルに設け(どういう方法でも良い)、その値をPythonコードにする。私の場合、Visual Studioでエディターが使えるSettings.settingsファイルを使って、「完成したCONFIGファイルのイメージ」のようなものを作った。

Pythonコードを実行

いよいよPythonコードを実行する。コード(C# 3.0以降)は次のようになる。

var code = Settings.Default.PythonCode; // 設定値を取得
_pythonCodeTextBox.Text = code;
var result = Python.CreateEngine().Execute(code); // コードを実行
_resultTextBox.Text = Convert.ToString(result);

ポイントは次の部分だ。

Python.CreateEngine().Execute(code)

完成

以上でアプリケーションが完成した。以下は、実際に動作させた様子だ。


注意:パフォーマンス

アプリケーションで実際にIronPython(など、DLR上で動作するライブラリ)を使う場合、パフォーマンスに要注意だ。それを使わないアプリケーションに比べパフォーマンスが遅くなる要因を、以下に挙げる。

  • Pythonコードのコンパイルが、アプリケーションの実行時に行われる
  • Pythonコードの実行が、(おそらく)リフレクションによる

実際に私が割と本格的なアプリケーションを作った経験から言うと、IronPythonを使うことで、パフォーマンスは劇的に悪化した感じがある。実際にはそのアプリケーションのIronPythonを使わないバージョンを作ったわけではないので、正確なことは言えないが、感覚的に明らかだった。

アプリケーション開発者にできることは、Pythonコードの不要なコンパイルを避けることぐたいだろうか。これはDLRの仕様なのだが、CompiledCodeクラスというのがあって、コードのコンパイル結果をキャッシュできる。何度も実行するコードがあるなら、そのコンパイル結果をキャッシュすべきだろう。

注意:セキュリティ

本エントリでは書ききれなかったが、IronPythonの大きな特長の1つが、.NET Frameworkのクラスを全て利用可能な点だ。つまりこれは、Pythonコードから何でもできることを意味する。例えば、CONFIGファイルを記述しさえすれば、本エントリで作成したアプリケーションから、スパムメールを送信することさえできてしまうはずだ。これは、重大なセキュリティリスクとなり得る。

この問題にどう対処するのか。私は実際に検証したわけではないので責任は持てないのだが、コードアクセスセキュリティがキーワードなのではないか。こう私が考えた理由は単純で、今回のサンプルアプリケーションでも使ったCreateEngineメソッドに、AppDomainを引数に取るオーバーロードがあるからだ。例えばネットワークに接続できないよう設定したAppDomainを渡すことで、Pythonコードからスパムメールを送ることはできなくなるのではないか。私は今のところ、この真否を確かめられていない*3

まとめ

IronPythonを使えば、コードをビルドし直すことなく動的に動作を変更できるアプリケーションを、実装できることが分かった。ただしその使用には、パフォーマンス、およびセキュリティという非常に重要な点で、注意が必要でもある。つまり、「柔軟性と堅牢性のトレードオフ」を見極めることが、重要だ。

*1:名前がださいぞ!?

*2:CLRより下の層は省略

*3:誰か確かめていただければ、とても嬉しいです。