Для надежного решения, которое сохраняет пробелы и комментарии, вы можете использовать модуль lib2to3
для анализа и очистки всех простых узлов операторов (обозначается simple_stmt
в грамматике Python из Grammar.txt ) из файла, которому принадлежит родительский фрейм, и возвращает узел, чей номер начальной строки и количество строк (рассчитанное путем подсчета количества символов новой строки) покрывают номер строки фрейма. Обратите внимание, что узел оператора не содержит предшествующего отступа, если он находится в начале блока кода, поэтому вам придется получить отступ от предыдущего узла-брата, если это узел пробелов:
from lib2to3 import fixer_base, refactor
class StatementScraper(fixer_base.BaseFix):
PATTERN = 'simple_stmt'
def __init__(self, lineno):
super().__init__(None, None)
self.lineno = lineno
self.statement = ''
def transform(self, node, result):
if not self.statement and self.lineno - node.get_lineno() < str(node).count('\n'):
prev_sibling = str(node.prev_sibling)
if prev_sibling.isspace():
self.statement += prev_sibling.lstrip('\n')
self.statement += str(node)
return node
class get_statement(refactor.RefactoringTool):
def __init__(self, source, lineno):
self.source = source
self.scraper = StatementScraper(lineno)
super().__init__(None)
def get_fixers(self):
return [self.scraper], []
def __str__(self):
self.refactor_string(self.source, '')
return self.scraper.statement
так что:
import inspect
def a(x, y, z):
frame = inspect.stack()[1].frame
print(get_statement(open(frame.f_code.co_filename).read(), frame.f_lineno))
def b():
a(
1,
2,
3,
)
b()
выходы:
a(
1,
2,
3,
)
Демо: https://repl.it/@blhsing/HotpinkOpenCgibin