How can I get the source code of a Python function?

后端 未结 12 1854
情话喂你
情话喂你 2020-11-22 02:39

Suppose I have a Python function as defined below:

def foo(arg1,arg2):
    #do something with args
    a = arg1 + arg2
    return a

I can g

相关标签:
12条回答
  • 2020-11-22 03:04

    You can use inspect module to get full source code for that. You have to use getsource() method for that from the inspect module. For example:

    import inspect
    
    def get_my_code():
        x = "abcd"
        return x
    
    print(inspect.getsource(get_my_code))
    

    You can check it out more options on the below link. retrieve your python code

    0 讨论(0)
  • 2020-11-22 03:06

    If the function is from a source file available on the filesystem, then inspect.getsource(foo) might be of help:

    If foo is defined as:

    def foo(arg1,arg2):         
        #do something with args 
        a = arg1 + arg2         
        return a  
    

    Then:

    import inspect
    lines = inspect.getsource(foo)
    print(lines)
    

    Returns:

    def foo(arg1,arg2):         
        #do something with args 
        a = arg1 + arg2         
        return a                
    

    But I believe that if the function is compiled from a string, stream or imported from a compiled file, then you cannot retrieve its source code.

    0 讨论(0)
  • 2020-11-22 03:06

    While I'd generally agree that inspect is a good answer, I'd disagree that you can't get the source code of objects defined in the interpreter. If you use dill.source.getsource from dill, you can get the source of functions and lambdas, even if they are defined interactively. It also can get the code for from bound or unbound class methods and functions defined in curries... however, you might not be able to compile that code without the enclosing object's code.

    >>> from dill.source import getsource
    >>> 
    >>> def add(x,y):
    ...   return x+y
    ... 
    >>> squared = lambda x:x**2
    >>> 
    >>> print getsource(add)
    def add(x,y):
      return x+y
    
    >>> print getsource(squared)
    squared = lambda x:x**2
    
    >>> 
    >>> class Foo(object):
    ...   def bar(self, x):
    ...     return x*x+x
    ... 
    >>> f = Foo()
    >>> 
    >>> print getsource(f.bar)
    def bar(self, x):
        return x*x+x
    
    >>> 
    
    0 讨论(0)
  • 2020-11-22 03:07

    Please mind that the accepted answers work only if the lambda is given on a separate line. If you pass it in as an argument to a function and would like to retrieve the code of the lambda as object, the problem gets a bit tricky since inspect will give you the whole line.

    For example, consider a file test.py:

    import inspect
    
    def main():
        x, f = 3, lambda a: a + 1
        print(inspect.getsource(f))
    
    if __name__ == "__main__":
        main()
    

    Executing it gives you (mind the indention!):

        x, f = 3, lambda a: a + 1
    

    To retrieve the source code of the lambda, your best bet, in my opinion, is to re-parse the whole source file (by using f.__code__.co_filename) and match the lambda AST node by the line number and its context.

    We had to do precisely that in our design-by-contract library icontract since we had to parse the lambda functions we pass in as arguments to decorators. It is too much code to paste here, so have a look at the implementation of this function.

    0 讨论(0)
  • 2020-11-22 03:13

    To expand on runeh's answer:

    >>> def foo(a):
    ...    x = 2
    ...    return x + a
    
    >>> import inspect
    
    >>> inspect.getsource(foo)
    u'def foo(a):\n    x = 2\n    return x + a\n'
    
    print inspect.getsource(foo)
    def foo(a):
       x = 2
       return x + a
    

    EDIT: As pointed out by @0sh this example works using ipython but not plain python. It should be fine in both, however, when importing code from source files.

    0 讨论(0)
  • 2020-11-22 03:16

    Since this post is marked as the duplicate of this other post, I answer here for the "lambda" case, although the OP is not about lambdas.

    So, for lambda functions that are not defined in their own lines: in addition to marko.ristin's answer, you may wish to use mini-lambda or use SymPy as suggested in this answer.

    • mini-lambda is lighter and supports any kind of operation, but works only for a single variable
    • SymPy is heavier but much more equipped with mathematical/calculus operations. In particular it can simplify your expressions. It also supports several variables in the same expression.

    Here is how you can do it using mini-lambda:

    from mini_lambda import x, is_mini_lambda_expr
    import inspect
    
    def get_source_code_str(f):
        if is_mini_lambda_expr(f):
            return f.to_string()
        else:
            return inspect.getsource(f)
    
    # test it
    
    def foo(arg1, arg2):
        # do something with args
        a = arg1 + arg2
        return a
    
    print(get_source_code_str(foo))
    print(get_source_code_str(x ** 2))
    

    It correctly yields

    def foo(arg1, arg2):
        # do something with args
        a = arg1 + arg2
        return a
    
    x ** 2
    

    See mini-lambda documentation for details. I'm the author by the way ;)

    0 讨论(0)
提交回复
热议问题