Jelle
Jelle

Reputation: 13

(Python) How can I print the function name of a partial function

I am running a process where I add failed functions to a list to be retried later. I use partial for this. Now I want to print what function is being retried.

Example Code:

retry_queue = []

def foo():
    """ Try and run function_a """

    result = function_a()

    if !result:
        retry_queue.append(partial(function_a, args)

    return retry_queue


# run the foo function
foo()

# retry all the failed functions
for function in retry_queue:
    print("Now running function: %s", function)
    function()


Wanted output:

>>> Now running function: function_a
   

How can I change my code to produce the wanted result?

I tried printing the example code, but that just gave a pointer to an object of the function.

Upvotes: 1

Views: 2762

Answers (2)

Wombatz
Wombatz

Reputation: 5458

You can access the original function with the func attribute. See the docs for more information.

In case you pass regular functions, you should write a wrapper that extracts the name of partial objects or "normal" functions.

from functools import partial
from typing import Callable, Any

def callable_name(any_callable: Callable[..., Any]) -> str:
    if isinstance(any_callable, partial):
        return any_callable.func.__name__

    try:
        return any_callable.__name__
    except AttributeError:
        return str(any_callable)

Now callable_name(print) and callable_name(partial(print, "Hello,")) both return 'print'.

If you have to support other callables besides partial and functions, you can add cases to handle that.

Upvotes: 1

Minh-Long Luu
Minh-Long Luu

Reputation: 2751

In order to do this, you need to make a custom partial function to wrap your function to it, then you can use __name__:

from functools import partial, update_wrapper
retry_queue = []


def wrapped_partial(func, *args, **kwargs):
    partial_func = partial(func, *args, **kwargs)
    update_wrapper(partial_func, func)
    return partial_func

def function_a(args = 1):
    return None

def foo():
    """ Try and run function_a """
    result = function_a()
    args = 1
    if not result:
        retry_queue.append(wrapped_partial(function_a, args))
    return retry_queue


# run the foo function
foo()

# retry all the failed functions
for function in retry_queue:
    print("Now running function: " + function.__name__)
    function()

Output: Now running function: function_a

Upvotes: 1

Related Questions