Обнаружение импортированных объектов

1

Учитывая исходный код файла Python, я бы хотел обнаружить все импортированные объекты. Например, с учетом этого источника:

import mymod
from mymod2 import obj1, obj2, obj3
from mymod3 import aobj

Я хочу получить:

[('mymod2', 'obj1', 'obj2', 'obj3'), ('mymod3', 'aobj')]

Я уже пробовал это регулярное выражение:

r'from (?P<mod>[_\w\d]+) import (?:(?P<obj>[_\w\d]+)[,\s]?)+'

Но я получаю только первый импортированный объект:

[('mymod2', 'obj1'), ('mymod3', 'aobj')]
  • 4
    Кажется плохой идеей делать это с регулярными выражениями. Что если оператор import распространяется на несколько строк, используя обратную косую черту? Или круглые скобки? Как насчет импорта на уровне функций? Это слишком сложно для регулярных выражений.
  • 0
    ... Ты прав! : D
Теги:

2 ответа

8
Лучший ответ

Лучшим инструментом, чем регулярные выражения, является модуль ast, который поставляется с Python. Чтобы найти все операторы from ... import во внешней области a.py и распечатать все импортированные имена, вы можете использовать

import ast
code = open("a.py").read()
for node in ast.parse(code).body:
    if isinstance(node, ast.ImportFrom):
        for name in node.names:
            print name.name

Обратите внимание, что этот простой код будет пропускать любые операторы, которые не находятся непосредственно на уровне модуля, такие как операторы импорта внутри блока try. Это можно легко устранить, используя ast.walk() для перемещения по всем узлам.

  • 0
    +1 аст отличный инструмент.
  • 0
    Вау, аст это здорово!
2

Это плохая идея для текстовой обработки источника Python с использованием регулярных выражений. Лучшая идея (без зависимостей) заключается в том, чтобы включить ее в ваш script, затем наследовать с помощью Python:

#-- test.py (the file you're targeting)
from time import asctime
from re import match, search

#-- now to find its imports
>>> import test
>>> for imprt in dir(test):
...   imprt = getattr(test, imprt, None)
...   if not getattr(imprt, '__module__', None):
...     continue
...   if imprt.__module__ in result:
...     result[imprt.__module__].append(imprt.__name__)
...   else:
...     result[imprt.__module__] = [imprt.__name__]
... 
>>> result
{'re': ['match', 'search'], 'time': ['asctime']}
  • 0
    Да, но я бы предпочел не запускать модуль, поэтому я подумал, что смогу разобрать код.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню