Найти конкретные переменные внутри функции и вернуть их отсортированными - PullRequest
3 голосов
/ 24 ноября 2011

Прежде всего, спасибо за вашу помощь в дальнейшем.Я использую Python и пытаюсь найти в .py файле все его функции, начиная с имени «test_» и всех включенных переменных.Переменные, которые я ищу, имеют следующий формат: "var [" blabla "]".Итак, у меня есть пример:

def test_123:

    init = var["blabla1"]
    init2 = var["blabla2"]
    *somecode*

def test_456:

    init3 = var["blabla3"]
    init4 = var["blabla4"]
    *somecode*

Я уже написал скрипт, который возвращает все мои функциии переменные в HTML-файле.Но мне нужно отсортировать их, чтобы я мог работать с ними лучше.

Сейчас это так:

test_123,test456
var["blabla1"],var["blabla2"],...

И я хочу вот так:

test_123:

var["blabla1"]
var["blabla2"]

test_456:

var["blabla3"]
var["blabla4"]

РЕДАКТИРОВАТЬ: У меня есть это сейчас:

def suchentpar():
    fobj = open("2.py", "r")
    search = fobj.read()
    tpar = re.findall(r'var\[\"\w+\"\]',search)
    return tpar
    fobj.close()

def suchenseq():
    fobj = open("2.py", "r")
    search = fobj.read()
    seq = re.findall(r'test\_\w+',search)
    return seq
    fobj.close()

Ответы [ 3 ]

1 голос
/ 24 ноября 2011

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

Основная идея состоит в том, чтобы использовать пакет ast для анализа исходного кода Python и сканирования результата на наличиеопределения функций.Таким образом, вы не обнаружите ложных срабатываний , например, определение функции внутри строки или комментария.Пример:

# define strings for function test_foobar().
foobar="def test_foobar(): pass"

Этот вход содержит два неправильных совпадения и будет обнаружен с помощью регулярных выражений, если не будет тщательно обработан очень .Используя ast, это намного проще, чем вы думаете.Рабочий пример:

#!/usr/bin/env python

import ast
import sys

def test_foobar():
        pass

class FunctionNameFinder(ast.NodeVisitor):
        def visit_FunctionDef(self, node):
                if node.name.startswith("test_"):
                        print node.name, "on line", node.lineno

with open(sys.argv[1], 'rU') as f:
        FunctionNameFinder().visit(ast.parse("".join(f.readlines())))

Эта программа может быть запущена сама для обнаружения фиктивной функции в строке 6!

РЕДАКТИРОВАТЬ: Следующее расширение обнаружит некоторые назначения переменных, но не все.Просто чтобы указать направление.

        def visit_FunctionDef(self, node):
                if node.name.startswith("test_"):
                        print node.name, "on line", node.lineno
                self.generic_visit(node)

        def visit_Subscript(self, node):
                if isinstance(node.value, ast.Name) and \
                   isinstance(node.slice, ast.Index):
                        if isinstance(node.slice.value, ast.Str):
                                print '%s["%s"] on line %s' % (
                                        str(node.value.id),
                                        str(node.slice.value.s),
                                        node.lineno)
                        elif isinstance(node.slice.value, ast.Num):
                                print '%s[%s] on line %s' % (
                                        str(node.value.id),
                                        str(node.slice.value.n),
                                        node.lineno)

HTH.

0 голосов
/ 24 ноября 2011

Развивая предыдущие ответы, вы также можете использовать OrderedDict (python 2.7+) для поддержания порядка.

import re
from collections import OrderedDict

fcontent = '''
def test_a(self):
    var["hello"]
    var["world"]

def test_b(self):
    var["hola"]
    var["mundo"]
'''

dict_ = OrderedDict()
chunks = [chunk for chunk in fcontent.split('def') if chunk.strip()]
for chunk in chunks:
    print chunk
    tname = re.findall(r'test\_\w+', chunk)[0]
    vars = re.findall(r'var\[\"\w+\"\]', chunk)
    dict_[tname] = vars
print dict_

Л.

0 голосов
/ 24 ноября 2011

Во-первых, ваш код как есть никогда не будет запускаться fobj.close(), учитывая, что функции будут выходить через return строку выше ...

Тогда, способ получить то, что вы хотите, может быть:

import re

fcontent = '''
def test_a(self):
    var["hello"]
    var["world"]

def test_b(self):
    var["hola"]
    var["mundo"]
'''

dict_ = {}
chunks = [chunk for chunk in fcontent.split('def ') if chunk.strip()]
for chunk in chunks:
    tname = re.findall(r'test\_\w+', chunk)[0]
    vars = re.findall(r'var\[\"\w+\"\]', chunk)
    dict_[tname] = vars
for k, v in dict_.items():
    print k
    for e in v:
        print "\t%s" % e

ПРИМЕЧАНИЕ: В вышеприведенном коде я оставил регулярные выражения в том виде, в каком вы их написали, но, конечно, вы могли бы улучшить их и изменить, если хотите, первый re.findall в re.search. Другими словами: то, что выше, является просто демонстрацией, чтобы показать концепцию, но вы должны работать над крайними случаями и эффективностью ...

НТН!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...