Проанализируйте .py файл, считайте AST, измените его, затем запишите измененный исходный код обратно

Вы должны использовать

df.groupby('Class').ID.agg(list).reset_index()
Out[473]: 
       Class      ID
0  (A, B, C)     [1]
1  (H, A, D)  [3, 4]
2  (M, E, F)     [2]

, чтобы исправить свой код

df.groupby('Class')['ID'].aggregate(lambda x: x.tolist())
.
155
задан Jonathan Leffler 3 May 2015 в 01:49
поделиться

4 ответа

Pythoscope does this to the test cases it automatically generates as does the 2to3 tool for python 2.6 (it converts python 2.x source into python 3.x source).

Both these tools uses the lib2to3 library which is a implementation of the python parser/compiler machinery that can preserve comments in source when it's round tripped from source -> AST -> source.

The rope project may meet your needs if you want to do more refactoring like transforms.

The ast module is your other option, and there's an older example of how to "unparse" syntax trees back into code (using the parser module). But the ast module is more useful when doing an AST transform on code that is then transformed into a code object.

The redbaron project also may be a good fit (ht Xavier Combelle)

69
ответ дан 23 November 2019 в 21:57
поделиться

The builtin ast module doesn't seem to have a method to convert back to source. However, the codegen module here provides a pretty printer for the ast that would enable you do do so. eg.

import ast
import codegen

expr="""
def foo():
   print("hello world")
"""
p=ast.parse(expr)

p.body[0].body = [ ast.parse("return 42").body[0] ] # Replace function body with "return 42"

print(codegen.to_source(p))

This will print:

def foo():
    return 42

Note that you may lose the exact formatting and comments, as these are not preserved.

However, you may not need to. If all you require is to execute the replaced AST, you can do so simply by calling compile() on the ast, and execing the resulting code object.

56
ответ дан 23 November 2019 в 21:57
поделиться

You might not need to re-generate source code. That's a bit dangerous for me to say, of course, since you have not actually explained why you think you need to generate a .py file full of code; but:

  • If you want to generate a .py file that people will actually use, maybe so that they can fill out a form and get a useful .py file to insert into their project, then you don't want to change it into an AST and back because you'll lose all formatting (think of the blank lines that make Python so readable by grouping related sets of lines together) (ast nodes have lineno and col_offset attributes) comments. Instead, you'll probably want to use a templating engine (the Django template language, for example, is designed to make templating even text files easy) to customize the .py file, or else use Rick Copeland's MetaPython extension.

  • If you are trying to make a change during compilation of a module, note that you don't have to go all the way back to text; you can just compile the AST directly instead of turning it back into a .py file.

  • But in almost any and every case, you are probably trying to do something dynamic that a language like Python actually makes very easy, without writing new .py files! If you expand your question to let us know what you actually want to accomplish, new .py files will probably not be involved in the answer at all; I have seen hundreds of Python projects doing hundreds of real-world things, and not a single one of them needed to ever writer a .py file. So, I must admit, I'm a bit of a skeptic that you've found the first good use-case. :-)

Update: now that you've explained what you're trying to do, I'd be tempted to just operate on the AST anyway. You will want to mutate by removing, not lines of a file (which could result in half-statements that simply die with a SyntaxError), but whole statements — and what better place to do that than in the AST?

19
ответ дан 23 November 2019 в 21:57
поделиться

Система преобразования программ - это инструмент, который анализирует исходный текст, строит AST, позволяет изменять их с помощью преобразования исходного текста в исходный. преобразования («если вы видите этот шаблон, замените его этим шаблоном»). Такие инструменты идеально подходят для изменения существующих исходных кодов, которые просто «если вы видите этот шаблон, замените его вариантом».

Конечно, вам нужен механизм преобразования программ, который может анализировать интересующий вас язык и при этом выполнять преобразования, ориентированные на шаблоны. Наша DMS Software Reengineering Toolkit - это система, которая может это делать и поддерживает Python и множество других языков.

См. Этот SO-ответ, в котором приведен пример AST, анализируемого с помощью DMS, для точного захвата комментариев Python . DMS может вносить изменения в AST и восстанавливать действительный текст, включая комментарии. Вы можете попросить его распечатать AST, используя свои собственные соглашения о форматировании (вы можете изменить их), или выполнить «точную печать», которая использует исходную информацию о строке и столбце для максимального сохранения исходного макета (некоторые изменения в макете, когда новый код вставляется неизбежно).

Чтобы реализовать правило «мутации» для Python с DMS, вы можете написать следующее:

rule mutate_addition(s:sum, p:product):sum->sum =
  " \s + \p " -> " \s - \p"
 if mutate_this_place(s);

Это правило заменяет «+» на «-» синтаксически правильным способом; он работает с AST и поэтому не затрагивает строки или комментарии, которые выглядят правильно. Дополнительное условие для "mutate_this_place" - позволить вам контролировать, как часто это происходит; вы не хотите изменять каждое место в программе.

Вы, очевидно, захотите создать еще несколько таких правил, которые обнаруживают различные структуры кода и заменяют их измененными версиями. DMS с радостью применяет набор правил. Затем мутировавший AST хорошо печатается.

2
ответ дан 23 November 2019 в 21:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: