C
でのプログラミング以前は、デバッグ目的(コマンドのロギングなど)にのみコードセクションを使用していました。これらのステートメントは、#ifdef
次のようなプリプロセッサディレクティブ:
#ifdef MACRO
controlled text
#endif /* MACRO */
python
で似たようなことをする最良の方法は何ですか?
ロギングメソッドを無効にするだけの場合は、logging
モジュールを使用します。ログレベルがデバッグステートメントなどを除外するように設定されている場合、logging.debug
はno-opに非常に近くなります(ログレベルをチェックし、ログ文字列を補間せずに戻ります)。
特定の変数を条件として、バイトコードのコンパイル時にコードのチャンクを実際に削除したい場合、唯一のオプションはかなり謎めいた__debug__
グローバル変数です。この変数は、-O
フラグがPythonに渡される場合(またはTrue
が環境内で空でないものに設定される場合)を除き、PYTHONOPTIMIZE
に設定されます。
__debug__
がif
ステートメントで使用されている場合、if
ステートメントは実際にはTrue
ブランチのみにコンパイルされます。この特定の最適化は、Pythonこれまでのようにプリプロセッサマクロに近いものです。
マクロとは異なり、if
の両方のブランチでコードが構文的に正しい必要があることに注意してください。
__debug__
がどのように機能するかを示すために、次の2つの関数を検討してください。
def f():
if __debug__: return 3
else: return 4
def g():
if True: return 3
else: return 4
dis
でチェックアウトしてください:
>>> dis.dis(f)
2 0 LOAD_CONST 1 (3)
3 RETURN_VALUE
>>> dis.dis(g)
2 0 LOAD_GLOBAL 0 (True)
3 JUMP_IF_FALSE 5 (to 11)
6 POP_TOP
7 LOAD_CONST 1 (3)
10 RETURN_VALUE
>> 11 POP_TOP
3 12 LOAD_CONST 2 (4)
15 RETURN_VALUE
16 LOAD_CONST 0 (None)
19 RETURN_VALUE
ご覧のとおり、「最適化」されているのはf
のみです。
Python 2&3 for my Python= Tkプログラムを区別するために使用する例を示します。
import sys if sys.version_info [0] == 3: from tkinter import * from tkinter import ttk else: from Tkinter import * import ttk "" "残りのコード" ""
それが有用な例であることを願っています。
In Python def
とclass
は2つの通常の実行可能ステートメントであることを理解することが重要です...
import os
if os.name == "posix":
def foo(x):
return x * x
else:
def foo(x):
return x + 42
...
cおよびC++のプリプロセッサで行うことを行うには、通常のPython言語を使用できます。
Python言語はこの点でCやC++と根本的に異なります。「コンパイル時間」という概念が存在せず、2つのフェーズが「解析時間」(ソースコードの読み込み時)と解析されたコードの「実行時」 (通常は主に定義ステートメントで構成されますが、実際には任意のPythonコード)が実行されます。
CとC++のコンパイルのセマンティクスが異なり、たとえば関数の定義がその段階で行われるため、技術的に変換でソースコードが読み取られるときにバイトコードへの完全なコンパイルである場合でも、用語「解析時間」を使用しています代わりに、Pythonの実行時に発生します)。
CおよびC++の#include
(Pythonのimport
は)に相当)は、コンパイルではなく実行時に実行される通常のステートメントです(解析します) )通常のpython if
。内に配置できるようになります。たとえば、import
ブロック内にtry
特定のオプションのPythonライブラリがシステムに存在しない場合、一部の関数の代替定義を提供します。
最後に、Pythonでは、ソースコードに必ずしもそれらを含める必要はありませんが、exec
を使用して、実行時に新しい関数やクラスを最初から作成することもできます。クラスと関数は実際には単なる通常のオブジェクトであるため、コードを直接使用するこれらのオブジェクト(これは通常、クラスに対してのみ行われます)。
代わりにdef
およびclass
の定義とimport
ステートメントを「静的」と見なそうとするツールがいくつかあります。たとえば、Python不審なフラグメントに関する警告を生成するコード、または特定のPythonプログラムを実行するシステムへのインストールに依存しない自己完結型の展開可能なパッケージを作成するコード。ただし、この領域ではPythonはCまたはC++よりも動的であり、自動分析が失敗する場所に例外を追加できることを考慮する必要があります。
私の知る限り、実際のif
ステートメントを使用する必要があります。プリプロセッサがないため、プリプロセッサディレクティブに類似するものはありません。
編集:実際には、この質問の一番上の答えがより明らかになるように見えます: Pythonでプリプロセッサディレクティブに相当する方法は何ですか?
特別な変数__debug__
があり、if
ステートメントと一緒に使用すると、一度評価された後、実行中に再度評価されることはありません。
私が知っている直接的な同等物はないので、ズームアウトして、プリプロセッサを使用して解決するために使用した問題を再検討することができます。
診断ログだけの場合は、必要なものすべてをカバーする包括的なログモジュールがあります。
http://docs.python.org/library/logging.html
他に何をプリプロセッサを使用しますか?テスト構成?そのための設定モジュールがあります。
http://docs.python.org/library/configparser.html
他に何か?
#ifdef
を使用して、現在のファイルの上のスコープで定義されている可能性のある変数をチェックしている場合、例外を使用できます。たとえば、ipython
とipython
の外部(たとえば、プロットを表示するかプロットを保存するか)から異なる方法で実行したいスクリプトがあります。だから私は追加します
ipy = False
try:
ipy = __IPYTHON__
except NameError:
pass
これにより、変数ipy
が残ります。この変数は、__IPYTHON__
が現在のスクリプトの上のスコープで宣言されたかどうかを示します。これは、Pythonの#ifdef
関数について知っている最も近い並列です。
ipython
の場合、これは優れたソリューションです。他のコンテキストでも同様の構成を使用できます。この場合、呼び出し元のスクリプトが変数値を設定し、それに応じて内部スクリプトがチェックします。もちろん、これが理にかなっているかどうかは、特定のユースケースに依存します。
Spyderで作業している場合、おそらくこれだけが必要です:
try:
print(x)
except:
#code to run under ifndef
x = "x is defined now!"
#other code
最初にスクリプトを実行すると、#code to run under ifndef
の下でコードが実行され、2回目はスキップします。うまくいくことを願っています:)
私は自分で試したことはありませんが、どうですか https://code.google.com/p/pypreprocessor/
これは、次のようにコマンドライン引数を渡すことで実現できます。
import sys
my_macro = 0
if(len(sys.argv) > 1):
for x in sys.argv:
if(x == "MACRO"):
my_macro = 1
if (my_macro == 1):
controlled text
次のスクリプトを実行して、この後の結果を確認してください。
python myscript.py MACRO
お役に立てれば。