Поиск зависимостей в исходном коде/скрипте python



У меня есть куча простых скриптов на Python с простыми выражениями[1], такими как:



C = A+B
D = C * 4


Мне нужно их выполнить, но самое главное-знать, от каких объектов я завишу; в предыдущем случае объект A и B являются внешними зависимостями. Напр.. учитывая, что у меня есть прежний код в var под названием source, я хочу иметь возможность:

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


Поэтому строго необходимо знать, как построить dictdeps .

Я прятался в AST Python модуль, но я понятия не имел.





[1] простые математические агрегации, до некоторой степени for циклы, не более.

622   1  

1 ответ:

Вы можете маркировать исходный код Python с помощью модуляtokenize из стандартной библиотеки. Это позволит вам найти все имена переменных, используемые в скрипте.

Теперь предположим, что мы определяем "не-зависимость" как любое имя переменной, которое непосредственно предшествует знаку =. Затем, в зависимости от того, насколько прост ваш код скрипта (см. предупреждения ниже), вы можете определить имена переменных, которые не являются независимыми. способ:
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 не является один зависимость.

Comments

    Ничего не найдено.