# 24 `codeop` -- Pythonコードをコンパイルする

`code`モジュールで行われているようなPythonのread-eval-printループをエミュレートするユーティリティを`codeop`モジュールは提供します。結果的に、直接モジュールを使いたいとは思わないかもしれません。あなたのプログラムにこのようなループを含めたい場合は、代わりに`code`モジュールを使うことをおそらく望むでしょう。

この仕事には二つの部分があります:

1. 入力の一行がPythonの文として完全であるかどうかを見分けられること: 簡単に言えば、次が``>`>`>` 'か、あるいは``...` 'かどうかを見分けます。
2. どのfuture文をユーザが入力したのかを覚えていること。したがって、実質的にそれに続く入力をこれらとともにコンパイルすることができます。

`codeop`モジュールはこうしたことのそれぞれを行う方法とそれら両方を行う方法を提供します。

前者は実行するには:

`compile_command`( | source[, filename[, symbol]])

  Pythonコードの文字列であるべきsourceをコンパイルしてみて、sourceが有効なPythonコードの場合はコードオブジェクトを返します。このような場合、コードオブジェクトのファイル名属性は、デフォルトで`'<input>'`であるfilenameでしょう。sourceが有効なPythonコードではないが、有効なPythonコードの接頭語である場合には、`None`を返します。

  sourceに問題がある場合は、例外を発生させます。無効なPython構文がある場合は、`SyntaxError`を発生させます。また、無効なリテラルがある場合は、`OverflowError`または`ValueError`を発生させます。

  symbol引数はsourceが文としてコンパイルされるか(`'single'`、デフォルト)、または式としてコンパイルされたかどうかを決定します(`'eval'`)。他のどんな値も`ValueError`を発生させる原因となります。

  警告: ソースの終わりに達する前に、成功した結果をもってパーサは構文解析を止めることが(できそうではなく)できます。このような場合、後ろに続く記号はエラーとならずに無視されます。例えば、改行が後ろに付くバックスラッシュには不定のゴミが付いているかもしれません。パーサのAPIがより良くなればすぐに、これは修正されるでしょう。

クラス `Compile`( | )

  このクラスのインスタンスは組み込み関数`compile()`とシグネチャが一致する`__call__()`メソッドを持っていますが、インスタンスが`__future__`文を含むプログラムテキストをコンパイルする場合は、インスタンスは有効なその文とともに続くすべてのプログラムテキストを'覚えていて'コンパイルするという違いがあります。

クラス `CommandCompiler`( | )

  このクラスのインスタンスは`compile_command()`とシグネチャが一致する`__call__()`メソッドを持っています。インスタンスが`__future__`文を含むプログラムテキストをコンパイルする場合に、インスタンスは有効なその文とともにそれに続くすべてのプログラムテキストを'覚えていて'コンパイルするという違いがあります。

バージョン間の互換性についての注意: `Compile`と`CommandCompiler`はPython 2.2で導入されました。2.2のfuture-tracking機能を有効にするだけでなく、2.1とPythonのより以前のバージョンとの互換性も保ちたい場合は、次のようにかくことができます

    try:
        from codeop import CommandCompiler
        compile_command = CommandCompiler()
        del CommandCompiler
    except ImportError:
        from codeop import compile_command

これは影響の小さい変更ですが、あなたのプログラムにおそらく望まれないグローバル状態を導入します。または、次のように書くこともできます:

    try:
        from codeop import CommandCompiler
    except ImportError:
        def CommandCompiler():
            from codeop import compile_command
            return compile_command

そして、新たなコンパイラオブジェクトが必要となるたびに`CommandCompiler`を呼び出します。