0

私の主な目的は、分析のためにいくつかのステートメントを挿入できるように、Python ループを解析することです。

Normal code:
#A.py

[code Starts]
.
.
.
while [condition]:
    [statements]
    [statements]
    [statements]

.
.
.
[code ends]

インストルメント化されたコード:

Normal code:
#A.py

[code Starts]
.
.
.
count =0                                    <---------- inserted code 
print "Entry of loop"                       <---------- inserted code
while [condition]:
    print "Iteration Number " + count++     <---------- inserted code
    [statements]
    [statements]
    [statements]
print "Exit of loop"                        <---------- inserted code
.
.
.
[code ends]

私の目的は、適切なインデントで適切な場所に上記のコードを挿入することです。ループは for ループにすることもできます。上記のインストルメント化されたコードを実現するには、A.py ファイルのループを解析し、それらのコードを挿入する必要があります。

これらのループを解析し、ループの行番号を取得して計測できるようにする良い方法はありますか?

ありがとうございました

4

3 に答える 3

1

pyparsing完全な (?) Python 文法パーサーを含むサンプル ファイルがあります。長期的には、これは興味深いオプションになる可能性があります。特に、分析プロジェクトでより多くの機能が追加される場合:

于 2013-06-11T09:10:43.583 に答える
0

これを行う最も簡単な方法は、ファイルを 1 行ずつスキャンし、一致する行が見つかったらステートメントを追加することです。

次のコードは目的を果たしますが、まったく堅牢ではありません。

def add_info_on_loops(iterable):
    in_loop = False
    for line in iterable:
        if not in_loop:
            if line.startswith('for ') or line.startswith('while '):
                in_loop = True
                yield 'count = 0\n'
                yield 'print "Entry of loop"\n'
                yield line
                yield '    print "Iteration Number:", count'
                yield '    count += 1\n'
            else:
                yield line
        else:
            if not line.startswith('    '):
                in_loop = False
                yield 'print "Exit of loop"\n'
            yield line

使用法:

>>> code = StringIO("""[code Starts]
... .
... .
... .
... while [condition]:
...     [statements]
...     [statements]
...     [statements]
... 
... .
... .
... .
... [code ends]""")
>>> print ''.join(add_info_on_loops(code))
[code Starts]
.
.
.
count = 0
print "Entry of loop"
while [condition]:
    print "Iteration Number:", count    count += 1
    [statements]
    [statements]
    [statements]
print "Exit of loop"

.
.
.
[code ends]

コードの落とし穴:

  1. コードは、最上位レベルでループのみを処理します。のようなものif condition: for x in a: ...が認識されません。これは、ループがあるかどうかを確認する前に空白の行を削除することで解決できます (ただし、インデントのさまざまなレベルなどを考慮する必要があります)。
  2. ループにインデントされていない行があると、コードが壊れます。これは、たとえば、コードを空白行で「分割」し、IDE が空白を削除した場合に発生します。解決策は、インデントされていない行ではなく、空白でもインデントされていない行を待つことです。
  3. コードはインデント用のタブを処理しません (簡単に修正できます)
  4. このコードは、1 行のループを処理しません (例: for x in a: print x)。この場合、間違った出力が得られます。の後に何かがあるかどうかのチェックを簡単に修正しました:
  5. countネストされたループのサポートを追加したい場合、単一の変数を使用するのは面倒です。おそらくどこかに整数 ID があり、新しいループを見つけるたびに増分される IDなどcount_0の変数名を使用する必要があります。count_1
  6. コードは、キーボードからの空白を持たない括弧付きの式を処理しません。たとえば for(a,b) in x:、ループとして検出されず、whilefor (a,b) in x:が検出されます。これは簡単に解決できます。forまず、行がandで始まるかどうかを確認whileし、次の文字が文字、数字、アンダースコアであってはなりません (実際には python3 では Unicode 文字も使用でき、これはテストが難しくなりますが、可能です)。
  7. このコードは、インデントされたループ行で終わるソース コードを処理しません。たとえばfor x in a: indented_last_line_of_code()、exitは追加されません (この状況が発生しているかどうかを確認するために、関数の外側にprintチェックを追加することで簡単に修正できます)。in_loopfor

ご覧のとおり、要求したことを実行するコードを書くことはそれほど簡単ではありません。あなたができる最善の方法はast、コードを解析し、ツリーにアクセスして正しい場所にノードを追加し、コードに再度アクセスしてpythonソースコードを生成することだと思います(通常、ノードにはソースの行に表示があります)これにより、まったく同じコードをコピーして貼り付けることができます)。

于 2013-06-11T10:52:22.460 に答える