How to print Docstring of python function from inside the function itself?

88,831

Solution 1

def my_func():
    """Docstring goes here."""
    print my_func.__doc__

This will work as long as you don't change the object bound to the name my_func.

new_func_name = my_func
my_func = None

new_func_name()
# doesn't print anything because my_func is None and None has no docstring

Situations in which you'd do this are rather rare, but they do happen.

However, if you write a decorator like this:

def passmein(func):
    def wrapper(*args, **kwargs):
        return func(func, *args, **kwargs)
    return wrapper

Now you can do this:

@passmein
def my_func(me):
    print me.__doc__

And this will ensure that your function gets a reference to itself (similar to self) as its first argument, so it can always get the docstring of the right function. If used on a method, the usual self becomes the second argument.

Solution 2

This should work (in my tests it does, also included output). You could probably use __doc__ instead of getdoc, but I like it, so thats just what i used. Also, this doesn't require you to know the names of the class/method/function.

Examples both for a class, a method and a function. Tell me if it's not what you were looking for :)

from inspect import *

class MySelfExplaningClass:
    """This is my class document string"""

    def __init__(self):
        print getdoc(self)

    def my_selfexplaining_method(self):
        """This is my method document string"""
        print getdoc(getattr(self, getframeinfo(currentframe()).function))


explain = MySelfExplaningClass()

# Output: This is my class document string

explain.my_selfexplaining_method()

# Output: This is my method document string

def my_selfexplaining_function():
    """This is my function document string"""
    print getdoc(globals()[getframeinfo(currentframe()).function])

my_selfexplaining_function()

# Output: This is my function document string

Solution 3

This works:

def my_function():
  """Docstring for my function"""
  #print the Docstring here.
  print my_function.__doc__

my_function()

in Python 2.7.1

This also works:

class MyClass(object):
    def my_function(self):
        """Docstring for my function"""
        #print the Docstring here, either way works.
        print MyClass.my_function.__doc__
        print self.my_function.__doc__


foo = MyClass()

foo.my_function()

This however, will not work on its own:

class MyClass(object):
    def my_function(self):
        """Docstring for my function"""
        #print the Docstring here.
        print my_function.__doc__


foo = MyClass()

foo.my_function()

NameError: global name 'my_function' is not defined

Solution 4

There's quite a simple method for doing this that nobody has mentioned yet:

import inspect

def func():
    """Doc string"""
    print inspect.getdoc(func)

And this does what you want.

There's nothing fancy going on here. All that's happening is that by doing func.__doc__ in a function defers attribute resolution long enough to have looking up __doc__ on it work as you'd expect.

I use this with docopt for console script entry points.

Solution 5

As noted many times, using the function name is a dynamic lookup in the globals() directory. It only works in the module of the definition and only for a global function. If you want to find out the doc string of a member function, you would need to also lookup the path from the class name - which is quite cumbersome as these names can get quite long:

def foo():
    """ this is foo """
    doc = foo.__doc__
class Foo:
    def bar(self):
       """ this is bar """
       doc = Foo.bar.__doc__

is equivalent to

def foo():
    """ this is foo """
    doc = globals()["foo"].__doc__
class Foo:
    def bar(self):
       """ this is bar """
       doc = globals()["Foo"].bar.__doc__

If you want to look up the doc string of the caller, that won't work anyway as your print-helper might live in a completely different module with a completely different globals() dictionary. The only correct choice is to look into the stack frame - but Python does not give you the function object being executed, it only has a reference to the "f_code" code object. But keep going, as there is also a reference to the "f_globals" of that function. So you can write a function to get the caller's doc like this, and as a variation from it, you get your own doc string.

import inspect

def get_caller_doc():
    frame = inspect.currentframe().f_back.f_back
    for objref in frame.f_globals.values():
        if inspect.isfunction(objref):
            if objref.func_code == frame.f_code:
                return objref.__doc__
        elif inspect.isclass(objref):
            for name, member in inspect.getmembers(objref):
                if inspect.ismethod(member):
                    if member.im_func.func_code == frame.f_code:
                        return member.__doc__

and let's go to test it:

def print_doc():
   print get_caller_doc()

def foo():
   """ this is foo """
   print_doc()

class Foo:
    def bar(self):
       """ this is bar """
       print_doc()

def nothing():
    print_doc()

class Nothing:
    def nothing(self):
        print_doc()

foo()
Foo().bar()

nothing()
Nothing().nothing()

# and my doc

def get_my_doc():
    return get_caller_doc()

def print_my_doc():
    """ showing my doc """
    print get_my_doc()

print_my_doc()

results in this output

 this is foo 
 this is bar 
None
None
 showing my doc 

Actually, most people want their own doc string only to hand it down as an argument, but the called helper function can look it up all on its own. I'm using this in my unittest code where this is sometimes handy to fill some logs or to use the doc string as test data. That's the reason why the presented get_caller_doc() only looks for global test functions and member functions of a test class, but I guess that is enough for most people who want to find out about the doc string.

class FooTest(TestCase):
    def get_caller_doc(self):
        # as seen above
    def test_extra_stuff(self):
        """ testing extra stuff """
        self.createProject("A")
    def createProject(self, name):
        description = self.get_caller_doc()
        self.server.createProject(name, description)

To define a proper get_frame_doc(frame) with sys._getframe(1) is left to the reader().

Share:
88,831

Related videos on Youtube

shane87
Author by

shane87

Software Developer - Dublin, Ireland.

Updated on July 08, 2022

Comments

  • shane87
    shane87 almost 2 years

    I want to print the docstring of a python function from inside the function itself. for eg.

    def my_function(self):
      """Doc string for my function."""
      # print the Docstring here.
    

    At the moment I am doing this directly after my_function has been defined.

    print my_function.__doc__
    

    But would rather let the function do this itself.

    I have tried calling print self.__doc__ print self.my_function.__doc__ and print this.__doc__ inside my_function but this did not work.

  • shane87
    shane87 over 12 years
    sorry guys my stupidity self.my_function.__doc__ actually works
  • Alex Leach
    Alex Leach over 12 years
    Your class method only works becuase you defined my_function as a function previously, in the global namespace. Try it with a fresh python instance ;)
  • shane87
    shane87 over 12 years
    is there any good way to not have to repeat the method name itself? something like this.__doc__ or something? sorry im new to python..
  • eyquem
    eyquem over 12 years
    @jgritty You didn't test your second snippet. It doesn't work
  • Alex Leach
    Alex Leach over 12 years
    yea, not really.. I had a look through dir( self.my_function ), and self.my_function.__func__ looked perhaps of interest, but it still needs to be accessed through that object model. You could add a function like this: for method in dir(MyClass): if hasattr(getattr(MyClass,method),'__doc__'): print getattr( getattr( MyClass,method), '__doc__')
  • Alex Leach
    Alex Leach over 12 years
    obeviously that indentation's not too useful. I'll put it in my original answer...
  • eyquem
    eyquem over 12 years
    @Alex Leach Did you test the snippet with the class ? It doesn't work, in fact....
  • eyquem
    eyquem over 12 years
    @jgritty and Alex Leach. Methods, id est functions defined in a class, are not able to know the outside space of them. See this question (stackoverflow.com/questions/1765677/python-nested-classes-s‌​cope/…) and my answer to it
  • Alex Leach
    Alex Leach over 12 years
    no, I didn't, but I assumed jgritty might have done. Just did test it, it works fine and as expected (change the docstring of the method, still prints the function docstring). Functions defined in the module are available inside class methods. e.g. There's no need to reimport something in a class method if it was imported at the top of the script..
  • Alex Leach
    Alex Leach over 12 years
    All tested in a single python interpreter instance btw. The Class snippet wouldn't work on it's own, I agree ;)
  • jgritty
    jgritty over 12 years
    Sure enough, I made a mistake. I've edited the example so it does in fact work now.
  • Tehnix
    Tehnix over 12 years
    @shane87, AlexLeach and MattLuongo: See my answer for a way to not repeat the class/method/function name.
  • FlipMcF
    FlipMcF over 12 years
    I really like your decorator method. Much more pythonic and less risky than frame inspection, AND allows you to avoid using the function name. Slick! Upvoted!
  • RufusVS
    RufusVS almost 7 years
    But the question was to report entrance into a function, not upon instantiation of a class.
  • RufusVS
    RufusVS almost 7 years
    Shouldn't the *args and **kwargs be in the argument list of my_func in the last code snippet? Or were additional arguments simply omitted, though the programmer could put any additional arguments desired in the function definition. I'm not sure that's clear, though it does say in the text "as its first argument".
  • kindall
    kindall almost 7 years
    The idea is the wrapper needs to be able to take any args, because it has no way of knowing (at decoration time) what arguments the wrapped function takes. It then passes whatever args it gets to the wrapped function. If there are the wrong number, you get an error at that point.
  • emorphus
    emorphus almost 7 years
    Sorry about that. Then it would be what is in the accepted answer. print func_name.__doc__
  • The Red Pea
    The Red Pea over 6 years
    @FlipMcF , I agree this approach is great, but what code here in this question or answer has actually performed "frame inspection"? EDIT Oh! Another possible answer, below: stackoverflow.com/a/25549647/1175496 I should just Ctrl+F :)
  • Reed_Xia
    Reed_Xia about 5 years
    But it's not better than just print func.__doc__
  • tripleee
    tripleee over 2 years
    The paragraph about deferring attribute resolution does not seem to be true. You cannot use func from within func because it is not yet defined. Perhaps this was different in Python 2...?