извлечение данных указанной функции в файл python | добавление комментариев, чтобы выделить то, что удалено - PullRequest
0 голосов
/ 25 февраля 2020

Я хочу извлечь код, написанный под указанной функцией. Я пытаюсь сделать это следующим образом:

С файлом примера TestFile.py, содержащим следующую функцию sub():

def sub(self,num1,num2):
    # Subtract two numbers
    answer = num1 - num2
    # Print the answer
    print('Difference = ',answer)

Если я запускаю get_func_data.py:

def giveFunctionData(data, function):
    dataRequired = []
    for i in range(0, len(data)):
        if data[i].__contains__(str(function)):
            startIndex = i
            for p in range(startIndex + 1, len(data)):
                dataRequired.append(data[p])
                if data[p].startswith('\n' + 'def'):
                    dataRequired.remove(dataRequired[len(dataRequired) - 1])
                    break
    print(dataRequired)
    return dataRequired

data = []
f = open("TestFile.py", "r")
for everyLine in f:
    if not(everyLine.startswith('#') or everyLine.startswith('\n' + '#')):
        data.append(everyLine)

giveFunctionData(data,'sub') # Extract content in sub() function

Я ожидаю получить следующий результат:

answer = num1 - num2
print('Difference = ',answer)

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

Ответы [ 3 ]

1 голос
/ 25 февраля 2020

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

Вы можете сделать одну вещь, создать функцию, которая принимает 2 аргумента, т.е. Имя файла и Имя функции. Функция должна возвращать нужный код.

Я создал функцию getFunctionCode (имя файла, имя_функции). Код работает хорошо.

def getFunctionCode(filename, funcname):
    data = []
    with open(filename) as fp:
        line = fp.readlines()
        startIndex = 0 #From where to start reading body part
        endIndex = 0 #till what line because file may have mult
    for i in range(len(line)): #Finding Starting index 
        if(line[i].__contains__(funcname)):
            startIndex = i+1
            break

    for i in range(startIndex,len(line)):
        if(line[i].__contains__('def')): #Find end in case - multiple function
            endIndex = i-1
            break
        else:
            endIndex = len(line)

    for i in range(startIndex,endIndex):
        if(line[i] != None):
            temp = "{}".format(line[i].strip())[0]
            if(temp != '\n' and  temp != '#'):
                data.append(line[i][:-1])
    return(data)

Я прочитал файл, указанный в первом аргументе. Затем выяснил индекс, где функция - это местоположение. Функция предусмотрена во втором аргументе. Начиная с индекса, я очистил строку и проверил первый символ, чтобы узнать о комментарии (#) и новой строке (\n). Наконец, строки без них добавляются.

Здесь вы можете найти файл TestFile.py:

def sub(self,num1,num2):
    # Subtract two numbers
    answer = num1 - num2
    # Print the answer
    print('Difference = ',answer)

def add(self,num1,num2):
    # addition of two numbers
    answer = num1 + num2
    # Print the answer
    print('Summation = ',answer)

def mul(self,num1,num2):
    # Product of two numbers
    answer = num1 * num2
    # Print the answer
    print('Product = ',answer)

Выполнение функции:

getFunctionCode('TestFile.py','sub')
['    answer = num1 - num2', "    print('Difference = ',answer)"]

getFunctionCode('TestFile.py','add')
['    answer = num1 + num2', "    print('Summation = ',answer)"]

getFunctionCode('TestFile.py','mul')
['    answer = num1 * num2', "    print('Product = ',answer)"]

enter image description here

Решение от MoltenMuffins также проще.

1 голос
/ 25 февраля 2020

Возвращение строки из вашей функции giveFunctionData()

В вашей функции giveFunctionData вы создаете экземпляр переменной dataRequired в виде списка и возвращаете ее после присвоения ей значения, поэтому, конечно, вы получить список обратно.

Вы должны распаковать список обратно в строку. Один из способов может быть следующим:

# Unpack the list into a string
function_content = ''
for line in dataRequired:
    function_content += line + '\n'
# function_content now contains your desired string

Причина, по которой вы все еще получаете строки комментариев

Итерации из файлового объекта, созданного с помощью open(), предоставят вам список строк из файла с \n уже используется в качестве разделителя строк. В результате нет \n# для .startswith('\n' + '#')), чтобы найти.

Общие комментарии

  1. Нет необходимости указывать символ новой строки и символ # отдельно, как вы это делали в .startswith('\n' + '#')). '\ n #' было бы хорошо

  2. Если вы намереваетесь запустить файл как скрипт, вы действительно должны поместить свой код для запуска в условное выражение if __name__ == "__main__":. См. Что означает, если name == « main »: do?

  3. Возможно, будет чище перемещать чтение объекта файла в вашу функцию giveFunctionData(). Это также устраняет необходимость повторять его несколько раз.


Собираем все вместе

Обратите внимание, что этот скрипт не может игнорировать комментарии, помещенные в та же строка, что и в коде (например, some = statement # With comments не будет зачеркнута)

def giveFunctionData(data, function):
    function_content = ''
    # Tells us whether to append lines to the `function_content` string
    record_content = False
    for line in data:
        if not record_content:
            # Once we find a match, we start recording lines
            if function in line:
                record_content = True
        else:
            # We keep recording until we encounter another function
            if line.startswith('def'):
                break
            elif line.isspace():
                continue
            elif '#' not in line:
                # Add line to `function_content` string
                function_content += line

    return function_content


if __name__ == "__main__":
    data = []
    script = open("TestFile.py")
    output = giveFunctionData(script, 'sub')
    print(output)
0 голосов
/ 25 февраля 2020

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

Более идеальным c и упрощенным c способом извлечения исходного кода функции из TestFile.py будет использовать метод inspect.getsource() следующим образом:

#Import necessary packages
import os
import sys
import inspect

#This function takes as input your pyton .py file and the function name in the .py file for which code is needed
def giveFunctionData(file_path,function_name):
    folder_path = os.path.dirname(os.path.abspath(file_path))
    #Change directory to the folder containing the .py file
    os.chdir(folder_path)
    head, tail = os.path.split(file_path)
    tail = tail.split('.')[0]
    #Contruct import statement for the function that needs to be imported
    import_statement = "from " + tail + " import " + function_name
    #Execute the import statement
    exec(import_statement)
    #Extract the function code with comments
    function_code_with_comments = eval("inspect.getsource("+function_name+")")
    #Now, filter out the comments from the function code
    function_code_without_comments = ''
    for line in function_code_with_comments.splitlines():
        currentstr = line.lstrip()
        if not currentstr.startswith("#"):
                                     function_code_without_comments = function_code_without_comments + line + '\n'    
    return function_code_without_comments


#Specify absolute path of your python file from which function code needs to be extracted
file_path = "Path_To_Testfile.py"
#Specify the name of the function for which code is needed
function_name = "sub"

#Print the output function code without comments by calling the function "giveFunctionData(file_path,function_name)"
print(giveFunctionData(file_path,function_name))

Этот метод будет работать для любого вида кода функции, который необходимо извлечь, независимо от форматирования файла .py, в котором присутствует функция вместо Разбор файла .py в качестве строковой переменной. Ура!

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