2013-06-11 3 views
0

Моя основная цель - разобрать петли python, чтобы я мог вставлять несколько инструкций для моего анализа.Как разобрать петли python, используя скрипт python?

Normal code: 
#A.py 

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

. 
. 
. 
[code ends] 

Instrumented код:

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 и вставить этот код.

Есть ли хороший способ проанализировать эти циклы и получить номер строки цикла, чтобы я мог использовать инструмент?

Спасибо

+1

Вы пытались сделать это с помощью модуля 'ast'? Эта задача очень похожа на [ваш предыдущий вопрос] (http://stackoverflow.com/q/16809248/222914). –

+0

@Janne Karila Да, мне действительно нужно точно так же, как в последнем вопросе. Но так как я никогда не использовал ast, я не знаю, какую функцию использовать. Было бы хорошо, если бы вы могли просто опубликовать простой сценарий? – Kaushik

+0

Предполагая, что вы проанализируете файл, как вы будете определять, какой цикл для инструмента, или вы все это используете? – chepner

ответ

1

Разборки обычно сложная задача. Вы можете использовать библиотеку python Pygments, которая является библиотекой подсветки синтаксиса. Это может показаться отличным от того, что вы намерены делать, но это не так. В конце концов, код окраски в основном добавляет информацию о цвете в блоки кода.

Использование PythonLexer позволяет извлекать токены для каждой строки и добавлять любые комментарии. Это пригодится, если вы не хотите просто работать с циклами, но также и для циклов, если инструкции ...

1

pyparsing имеет образец файла, содержащий полный (?) Паттерн грамматики Python. В долгосрочной перспективе это может быть интересный вариант - особенно если/когда ваш проект анализа получат больше возможностей:

0

Самый простой способ сделать это, чтобы просто просмотреть файл построчно по строке и добавлять инструкции, когда вы найдете строку, которая соответствует.

Следующий код делает то, что вы хотите, но это не прочный на всех:

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. Код не обрабатывает однострочные циклы (например, for x in a: print x). В этом случае вы получите неверный вывод. Легко фиксированная проверка наличия чего-то после :.
  5. Использование переменной count затруднено, если вы хотите добавить поддержку вложенных циклов. Вероятно, вы должны иметь целочисленный идентификатор и использовать имена переменных, такие как count_0, count_1 с идентификатором, который увеличивается каждый раз, когда вы находите новый цикл.
  6. Код не обрабатывает выражения с круглыми скобками, которые не имеют пробелов с клавиатуры. например for(a,b) in x: не определяется как цикл, а обнаружен for (a,b) in x:. Это легко решить. Сначала вы проверяете, начинается ли линия с for и while, а следующий символ не должен быть буквой, номером, подчеркиванием (на самом деле в python3 вы также можете использовать символы юникода, и это становится сложнее проверить, но возможно).
  7. Код не обрабатывает исходный код, который заканчивается отступом. например for x in a: indented_last_line_of_code() выход print не будет добавлен. (Легко установить добавление проверки на in_loop вне функции for функции, чтобы узнать, есть ли у нас такая ситуация).

Как вы можете видеть, написав фрагмент кода, который делает то, что вы просили, не так уж и тривиально. Я считаю, что лучше всего использовать ast, чтобы разобрать код, затем посетить дерево и добавить узлы в нужные места, затем повторно посетить код и сгенерировать исходный код python (обычно узлы имеют индикацию на строке в исходный код, который позволяет копировать и вставлять один и тот же код).

Смежные вопросы