2015-04-24 2 views
3

У меня есть функция, которая была создана с помощью exec() внутри другой функции и передана в качестве аргумента основной программе. Как я могу получить код указанной функции? Я попытался inspec.getsourcelines() и inspec.getsource(), но я получаю следующее сообщение об ошибкеpython - Как проверить код функции, созданный с помощью exec

IOError: could not get source code 

Есть ли способ обойти это?

MWE основной файл:

#!/usr/bin/python 
from ext import makeF 
import inspect 

f=makeF() 
f() 
inspect.getsource(f) 

затем внешний файл:

def makeF(): 
    script="def sayA():\n\tprint('Aah')" 
    exec(script) 
    return sayA 
+0

Можете добавить свой код в вопросе, чтобы сделать его более понятным! – Kasramvd

+1

Реальный код слишком длинный. Я сделаю паузу через некоторое время. – TomCho

ответ

1

В python 3 это атрибут функции __globals__.

С вашего примера:

>>> f.__globals__['txt'] 
"def sayA():\n\tprint('Aah')" 

К сожалению, я не мог найти что-нибудь подобное для Python 2.


Причина, почему другие методы не могут работать, потому что они используют имя файла модуль, и здесь у вас нет файла.

1

Это не представляется возможным. Я копался и пришел к тому же выводу, что и в this answer.

Я не знаю вашего кода, но я думаю, что в вашем конкретном случае вы могли бы вернуть пользовательский объект, содержащий исходный код функции (который у вас есть, вы передаете его в exec) вместе с фактическая скомпилированная функция. Вы могли бы использовать магический метод __call__ Python, чтобы лучше подражать оригинальному поведению. Вот пример:

class FunctionWithCode: 
    def __init__(self, source, func_name): 
     exec(source) 
     self.source = source 
     self.func = locals()[func_name] 

    def __call__(self, *args, **kwargs): 
     self.func(*args, **kwargs) 

f = FunctionWithCode("def sayA():\n\tprint('Aah')", 'sayA') 

f() 

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

+0

Я как-то решил это, заменив 'return sayA' на' return sayA, script', и таким образом я просто использовал его как переменную. Я просто подумал, что есть что-то, чего я не видел с «проверкой». Однако, обходной путь довольно хорош. Я думаю, что это можно легко обернуть, чтобы имя было получено простым анализом первой строки кода. – TomCho

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