Python でプリプロセッサ ディレクティブに相当することを行うにはどうすればよいでしょうか?
-
20-08-2019 - |
質問
Python で次のプリプロセッサ ディレクティブを実行する方法はありますか?
#if DEBUG
< do some code >
#else
< do some other code >
#endif
解決
コンパイラは前処理を行うことに特別な値である__debug__
が、あります。
if __debug__:
print "If this prints, you're not running python -O."
else:
print "If this prints, you are running python -O!"
if 0:
コンパイラによって定数0または1で置換され、ソースが解釈される前に、オプティマイザは、任意<=>行を削除します。
他のヒント
私は、あなたが説明していることを正確に実行する pypreprocessor という Python プリプロセッサを書きました。
パッケージは、PyPI を通じてダウンロード/インストールすることもできます。.
ここで説明していることを実現する例を示します。
from pypreprocessor import pypreprocessor
pypreprocessor.parse()
#define debug
#ifdef debug
print('The source is in debug mode')
#else
print('The source is not in debug mode')
#endif
pypreprocessor は、オンザフライの前処理以上の機能を備えています。さらに多くの使用例を確認するには、Google Code のプロジェクトをチェックしてください。
アップデート:pyプリプロセッサの詳細
前処理を実行する方法は簡単です。上記の例から、プリプロセッサは pypreprocessor モジュールで作成された pypreprocessor オブジェクトをインポートします。プリプロセッサ上で parse() を呼び出すと、プリプロセッサはインポート先のファイルを自己消費し、すべてのプリプロセッサ コードをコメント アウトした自身の一時コピーを生成します (プリプロセッサが無限ループで再帰的に自身を呼び出すのを避けるため)。未使用部分をすべてコメントアウトします。
行を削除するのではなくコメント アウトすることは、モジュールが例外をスローしたりクラッシュした場合にエラー トレースバックで行番号を保持するために必要です。さらに、クラッシュしたモジュールの適切なファイル名を反映するようにエラー トレースバックを書き換えることまでしました。
次に、後処理されたコードを含む生成されたファイルがオンザフライで実行されます。
コード内に多数の if ステートメントをインラインで追加するよりもこの方法を使用する利点は、コードのコメント化された部分がコンパイルされた .pyc ファイルから除外されるため、無駄なステートメントの評価に無駄な実行時間がなくなることです。
欠点 (およびモジュールを作成した最初の理由) は、Python インタープリターはコードを実行する前に完全な構文チェックを実行し、コードを実行する前にバージョン固有のコードを拒否するため、同じファイル内で Python 2x と Python 3x の両方を実行できないことです。プリプロセッサは ::sigh:: を実行できます。私の当初の目標は、同じファイル内で 2x と 3x のコードを並べて開発し、実行されているものに応じてバージョン固有のバイトコードを作成できるようにすることでした。
いずれにせよ、プリプロセッサ モジュールは、一般的な C スタイルの前処理機能を実装するのに非常に役立ちます。さらに、プリプロセッサは、必要に応じて、後処理されたコードをファイルに出力して、後で使用することもできます。
また、すべてのプリプロセッサ ディレクティブと除外された #ifdef が削除されたバージョンを生成する場合は、parse() を呼び出す前にプリプロセッサ コードにフラグを設定するだけで済みます。これにより、バージョン固有のソース ファイルから不要なコードを削除するのが 1 ステップのプロセスになります (コードをクロールして if ステートメントを手動で削除するのではありません)。
私はあなたがこの回答を憎むつもりだ疑い。あなたはPythonでそれを行う方法です。
# code here
if DEBUG:
#debugging code goes here
else:
# other code here.
Pythonのインタープリターであるので、、適用すべき前処理ステップ、及び特別な構文を有することのない特定の利点はありません。
あなたはPythonでプリプロセッサを使用することができます。ちょうどあなたのbinディレクトリにCPP(C-プリプロセッサ)を通して、あなたのスクリプトを実行します。しかし、私はLuaのでこれをやったし、容易な解釈の利点は、より複雑なコンパイルの私見を上回っています。
あなたは普通の言語構文を使用することができます:
DEBUG = True
if DEBUG:
# Define a function, a class or do some crazy stuff
def f():
return 23
else:
def f():
return 42
別の方法は、デバッグに関連するコードの部分をコメントアウトするbashスクリプトを使用することです。以下は、その中に「#デバッグ」ステートメントを持っている行をコメントアウトするサンプルスクリプトです。また、再度、これらのコメントマーカーを削除することができます。
if [ "$1" == "off" ]; then
sed -e '/^#/! {/#DEBUG/ s/^/#/}' -i *.py
echo "Debug mode to $1"
elif [ "$1" == "on" ]; then
sed -e '/#DEBUG/ s/^#//' -i *.py
echo "Debug mode to $1"
else
echo "usage: $0 on | off"
fi
- Python if は配列から要素を削除できません。
- C プリコンパイラは #! を処理しません。または必要に応じて # で始まる他の行を追加します。
- pypreprocessorはPython固有のようです
代わりに、次のように一般的な m4 を使用します。
ifelse(DEBUG,True,dnl`
< do some code >
dnl,dnl`
< do some other code >dnl
')
ifelse(
M4_CPU,x86_64,`
< do some code specific for M4_CPU >
',M4_CPU,arm,`
< do some code specific for M4_CPU >
',M4_CPU,ppc64le,`
< do some code specific for M4_CPU >
')
ifelse(
M4_OS,windows,`
< do some code specific for M4_OS >
',M4_OS,linux,`
< do some code specific for M4_OS >
',M4_OS,android,`
< do some code specific for M4_OS >
')
m4 -D DEBUG=True -D M4_OS=android -D M4_CPU=arm test.py.m4 > test.py