4

Pythonには、次のような単純な式[1]を使用した単純なスクリプトがたくさんあります。

C = A+B
D = C * 4

それらを実行する必要がありますが、最も重要なのは、依存しているオブジェクトが何であるかを知る必要があります。前のケースでは、オブジェクトABは外部依存関係です。例えば。ソースと呼ばれる変数に前のコードがあるとすると、次のことができるようになります。

deps = { "A" : 1 , "B": 2}
exec source in deps

したがって、 dictdepsを構築する方法を知る必要があります。

私はastPythonモジュールに潜んいますが、手がかりがありませんでした。


[1]単純な数学の集計、ある程度のforサイクル、それ以上のものはありません。

4

1 に答える 1

3

標準ライブラリのtokenizeモジュールを使用して、Pythonソースコードをトークン化できます。これにより、スクリプトで使用されているすべての変数名を見つけることができます。

=ここで、「非依存性」を、符号の直前にある変数名として定義するとします。次に、スクリプトコードが実際にどれほど単純であるかに応じて(以下の警告を参照)、この方法で非依存ではない変数名を判別できる場合があります。

import tokenize
import io
import token
import collections
import keyword

kwset = set(keyword.kwlist)
class Token(collections.namedtuple('Token', 'num val start end line')):
    @property
    def name(self):
        return token.tok_name[self.num]

source = '''
C = A+B
D = C * 4
'''

lastname = None
names = set()
not_dep = set()
for tok in tokenize.generate_tokens(io.BytesIO(source).readline):
    tok = Token(*tok)
    print(tok.name, tok.val)
    if tok.name == 'NAME':
        names.add(tok.val)
        lastname = tok.val
    if tok.name == 'OP' and tok.val == '=':
        not_dep.add(lastname)

print(names)
# set(['A', 'C', 'B', 'D'])
print(not_dep)
# set(['C', 'D'])

deps = dict.fromkeys(names - not_dep - kwset, 1)
print(deps)
# {'A': 1, 'B': 1}

警告

  • スクリプトに単純な割り当て以外のステートメントが含まれている場合、names不要な変数名が入力される可能性があります。例えば、

    import numpy
    

    'import'との両方を'numpy'セットに追加しnamesます。

  • スクリプトに、左側のタプルの解凍を利用する割り当てが含まれている場合。

    E, F = 1, 2
    

    その場合、上記の単純なコードは、それFが依存関係ではないことだけを認識します。

于 2013-01-04T22:46:33.433 に答える