# Get names of positional arguments in wrapping function

**URL:** <https://discuss.python.org/t/get-names-of-positional-arguments-in-wrapping-function/61308>\
**Category:** Python Help\
**Created:** [August 19, 2024, 5:51pm UTC](https://discuss.python.org/t/get-names-of-positional-arguments-in-wrapping-function/61308 "2024-08-19T17:51:38Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![yoavdw](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/yoavdw/32/15524_2.png) [@yoavdw](https://discuss.python.org/u/yoavdw)\
**Post date:** [August 19, 2024, 5:51pm UTC](https://discuss.python.org/t/get-names-of-positional-arguments-in-wrapping-function/61308/1 "2024-08-19T17:51:38Z")

</div>

Imagine this made-up decorator that tries to capture the arguments of the wrapped function and save them to some key-value store for logging purposes:

```python
import json
from functools import wraps

some_path = ...

def log_args_to_json(func):

    @wraps(func)
    def wrapper(*args, **kwargs):
        # What to do with the args?
        data = json.dumps("func_name": func. __name__ , "kwargs": kwargs)
        some_path.write_text(data)
        return func(*args, **kwargs)

    return wrapper

@log_args_to_json
def say_hello(name, suffix):
     print(f"Hello, {name}{suffix}")

```

With the following calls:

```python
say_hello("John", "!") # File has: {}
say_hello("John", suffix="!") # File has {"suffix": "!"}

```

This decorator doesn’t store the `*args` because the destination is a key-value store (I chose a JSON file for simplicity, but this could go anywhere) and it doesn’t know the argument names. It could store it as a list, but that would be much less readable to a person viewing the logs (they wouldn’t know what argument each value corresponds to)

Obviously, the decorator can’t just know the names of the arguments, because they are positional - and would correspond to different names for each function. **But** python **is** able to parse the function’s signature and figure out which positional argument corresponds to each value.

I’m wondering if there’s any simple way for me to do this in my code. Maybe I’m missing something incredibly obvious here, but it sucked that I had to make all my arguments keyword only just so I could get the names, when there clearly is a way for Python to figure it out. The only soluiton I could think of is analyzing the names using the function’s ` __code__ `, but that seems like it would be complicated (Again, maybe it’s simple and I’m wrong here).

---

<div class="post-metadata">

**Author:** ![Rosuav](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/rosuav/32/3429_2.png) [@Rosuav](https://discuss.python.org/u/Rosuav)\
**Post date:** [August 19, 2024, 5:59pm UTC](https://discuss.python.org/t/get-names-of-positional-arguments-in-wrapping-function/61308/2 "2024-08-19T17:59:14Z")

</div>

The [inspect module](https://docs.python.org/3/library/inspect.html) has a lot of what you’re looking for!

---

<div class="post-metadata">

**Author:** ![yoavdw](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/yoavdw/32/15524_2.png) [@yoavdw](https://discuss.python.org/u/yoavdw)\
**Post date:** [August 19, 2024, 6:10pm UTC](https://discuss.python.org/t/get-names-of-positional-arguments-in-wrapping-function/61308/3 "2024-08-19T18:10:29Z")

</div>

It seems like `Signature.bind` is exactly what I needed, that’s awesome! Thank you!

My fear with using a Signature object is this sentence from the documentation:

> Raises [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError) if no signature can be provided, and [`TypeError`](https://docs.python.org/3/library/exceptions.html#TypeError) if that type of object is not supported.

It sounds from this some callables aren’t supported. Do you happen to know when that might happen? I wouldn’t want to have an exception raised because of that, and would also like to know the limitations of signature.

---

<div class="post-metadata">

**Author:** ![MegaIng](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/megaing/32/16162_2.png) [@MegaIng](https://discuss.python.org/u/MegaIng)\
**Post date:** [August 19, 2024, 6:16pm UTC](https://discuss.python.org/t/get-names-of-positional-arguments-in-wrapping-function/61308/4 "2024-08-19T18:16:21Z")

</div>

AFAIK, this will only happen if the object is a builtin function or method and the implementor has not provided a ` __text_signature__ ` (or similar) attribute for inspect to use.

`TypeError` you will get if you pass in something that isn’t callable.

For normal python functions you don’t have to worry.

---

<div class="post-metadata">

**Author:** ![Rosuav](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/rosuav/32/3429_2.png) [@Rosuav](https://discuss.python.org/u/Rosuav)\
**Post date:** [August 19, 2024, 6:25pm UTC](https://discuss.python.org/t/get-names-of-positional-arguments-in-wrapping-function/61308/5 "2024-08-19T18:25:44Z")

</div>

> [@yoavdw](#):
>
> It sounds from this some callables aren’t supported. Do you happen to know when that might happen? I wouldn’t want to have an exception raised because of that, and would also like to know the limitations of signature.

You’re talking about standard Python functions so you shouldn’t have to worry about it. There are certain things that can be called but aren’t normal functions (mostly C-implemented), and as Megalng says, TypeError means it’s not a callable.

---

<div class="post-metadata">

**Author:** ![yoavdw](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/yoavdw/32/15524_2.png) [@yoavdw](https://discuss.python.org/u/yoavdw)\
**Post date:** [August 19, 2024, 6:36pm UTC](https://discuss.python.org/t/get-names-of-positional-arguments-in-wrapping-function/61308/6 "2024-08-19T18:36:06Z")

</div>

Thank you! Now I just have to figure out how to get this through a code review😅
