Поиск зависимостей в исходном коде/скрипте 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 циклы, не более.
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