49

プログラミングでのプログラミングC以前は、デバッグ目的 (コマンドのログ記録など) にのみ使用されるコード セクションを使用していました。これらのステートメントは#ifdef、次のようにプリプロセッサ ディレクティブを使用することで、本番用に完全に無効にすることができます。

 #ifdef MACRO

 controlled text

 #endif /* MACRO */

で同様のことを行う最良の方法は何pythonですか?

4

8 に答える 8

37

ロギング メソッドを無効にするだけの場合は、loggingモジュールを使用します。ログ レベルがデバッグ ステートメントなどを除外するように設定されている場合、logging.debugほとんど何も行われません (ログ レベルをチェックするだけで、ログ文字列を補間せずに返されます)。

特定の変数を条件として、バイトコードのコンパイル時にコードのチャンクを実際に削除したい場合、唯一のオプションはかなり謎めいた__debug__グローバル変数です。この変数は、フラグが Python に渡されTrueない限り(または環境で空でない値に設定されていない限り) に設定されます。-OPYTHONOPTIMIZE

をステートメントで__debug__使用すると、ステートメントは実際にはブランチのみにコンパイルされます。この特定の最適化は、Python がこれまでに得たものと同じくらいプリプロセッサ マクロに近いものです。ififTrue

マクロとは異なり、コードは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「最適化」されているだけです。

于 2012-09-21T05:42:53.467 に答える
9

Python Tk プログラムで Python 2 と 3 を区別するために使用する例を次に示します。

システムのインポート
sys.version_info[0] == 3 の場合:
    tkinterインポートから *
    tkinterインポートttkから
そうしないと:
    Tkinterインポートから *
    ttk をインポート

""" コードの残りの部分 """

役に立つイラストであることを願っています。

于 2016-04-06T21:23:59.100 に答える
9

defPython ではと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 では実行時に発生します)。

#includeC および C++ (Python では)に相当するものでさえ、importコンパイル (解析) 時ではなく実行時に実行される通常のステートメントであるため、通常の python 内に配置できますif。たとえば、特定のオプションの Python ライブラリがシステムに存在しない場合に、一部の関数の代替定義を提供する をブロックimport内に持つことは非常に一般的です。try

最後に、Python では、実行時に を使用して新しい関数やクラスをゼロから作成することもできますがexec、必ずしもソース コードに含める必要はありません。クラスと関数は実際には単なる通常のオブジェクトであるため、コードを使用してこれらのオブジェクトを直接アセンブルすることもできます (ただし、これは通常、クラスに対してのみ行われます)。

def代わりに、class定義とステートメントを「静的」と見なそうとするツールがいくつかありますimport。たとえば、Python コードの静的分析を行って、疑わしいフラグメントに関する警告を生成したり、所有することに依存しない自己完結型の展開可能なパッケージを作成したりします。プログラムを実行するためのシステム上の特定の Python インストール。ただし、Python はこの分野で C や C++ よりも動的であり、自動分析が失敗する場所に例外を追加できることをすべて考慮する必要があります。

于 2012-09-21T05:46:15.027 に答える
7

私の知る限り、実際のifステートメントを使用する必要があります。プリプロセッサがないため、プリプロセッサ ディレクティブに類似したものはありません。

編集: 実際には、この質問に対する一番の答えはより明確になるようです: Python でプリプロセッサ ディレクティブに相当するものをどのように実行しますか?

おそらく、ステートメントで__debug__使用されると、if一度評価され、実行中に再度評価されない特別な変数があると思われます。

于 2012-09-21T05:11:22.440 に答える
2

私が認識している直接の同等物はありません。したがって、ズームアウトして、プリプロセッサを使用して解決した問題を再考することをお勧めします。

それが単なる診断ログである場合は、必要なものすべてをカバーする包括的なログ モジュールがあります。

http://docs.python.org/library/logging.html

プリプロセッサを他に何に使用しますか? テスト構成?そのための構成モジュールがあります。

http://docs.python.org/library/configparser.html

他に何か?

于 2012-09-21T05:25:44.817 に答える