Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lots of people don't know functools.partial; document it better #88

Open
Carreau opened this issue Mar 11, 2017 · 4 comments
Open

Lots of people don't know functools.partial; document it better #88

Carreau opened this issue Mar 11, 2017 · 4 comments
Labels

Comments

@Carreau
Copy link
Contributor

Carreau commented Mar 11, 2017

First, if you care I wrote a curio/trio options for IPython's async repl integration (ipython/ipython#10390)

One thing I came across, is that you can't pass kwargs easily to function passed to run/Nursery.spawn:

In [9]: n.spawn?
Signature: n.spawn(async_fn, *args, name=None)

I think, this is a perfect use for positional only for async_fn not to grab a name if you want **kwargs.
There was a recent discussion on python idea about positional only.

I don't see any clean way of fixing this, except with an ugly api of the type:

trio.run.options(clock=None, instruments=[])(async_fn, /, *args, **kwargs)

Where option would return a "configured" run.

or allow a args, kwargs (no stars) parameters which are used when *args is empty:

run(async_fn, *args, clock=None, instruments=[], async_fn_args=None, async_fn_kwargs=None )

In my case I worked around with a second function wrapper:

def _trio_runner(function, user_ns):
    import trio
    def loc(fun, user_ns):
        return fun(**user_ns)
    return trio.run(loc, function, user_ns)
@njsmith
Copy link
Member

njsmith commented Mar 11, 2017

You can use functools.partial instead of defining your own wrapper.

But yeah, this is intentional, and I don't see how any Python enhancements can help – the basic problem is that we need some way to distinguish between arguments that belong to async_fn versus arguments that belong to run. And right now our convention is that positional arguments belong to async_fn and kwargs belong to run.

I don't understand the motivation for having an async_fn_args= kwarg – if you have an iterable of positional arguments, just use * :-). But it's an interesting idea that we could take a kwargs= kwarg though ... nothing stopping us. I'm not sure if it's really more elegant than functools.partial though?

# Door 1 (now)
trio.run(partial(some_fn, arg1, somearg=blah), clock=...)

# Door 2 (proposed)
trio.run(some_fn, arg1, kwargs=dict(somearg=blah), clock=...)

The first line looks nicer to me, though granted you need an extra import.

@Akuli
Copy link

Akuli commented May 16, 2017

I think run and spawn could use an API similar to threading.Thread, like nursery.spawn(thing, args=[1, 2], kwargs={'a': 3, 'b': 4}). It's a bit more writing but doesn't require people to be familiar with functools.partial.

@njsmith njsmith added the docs label Aug 20, 2017
@njsmith njsmith changed the title run,spawn and pass kwargs to function ? Lots of people don't know functools.partial; document it better Aug 20, 2017
@njsmith
Copy link
Member

njsmith commented Aug 20, 2017

Just renamed this – the sense I'm getting is that functools.partial really is the best solution, but it has a weird name and lots of people don't know about it, so just pointing at it is off-putting and confusing. So instead of adding extra ways to do it, what I'd like to try first is to improve the docs by giving examples in the tutorial and everywhere we mention it, so people realize how easy it is to use.

@Zac-HD
Copy link
Member

Zac-HD commented Jun 29, 2018

functools.partial is clearly explained in the API docs for trio.run, so adding an example in the tutorial would be enough to close this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants