Jorropo states: Polymorph function work exacly like async function BUT they assure of the > ability to execute syncronously. - sic >
Async functions can call sync functions, but not vice versa. Consider a third party solution - trio <https://github.com/python-trio/trio>, that allows sync functions to call async functions. >From the docs <https://trio.readthedocs.io/en/latest/tutorial.html#async-functions>: async def async_double(x): return 2 * x trio.run(async_double, 3) # returns 6 --- If you want a stdlib solution, let's revisit Nathaniel Smith's example: > def maybe_async(fn): > @functools.wraps(fn) > def wrapper(*args, **kwargs): > coro = fn(*args, **kwargs) > if asyncio.get_running_loop() is not None: > return coro > else: > return await coro > I was unable to run his example as-is (in Python 3.6 at least) since the `await` keyword is only permitted inside an `async def` function. However, the idea is intriguing and can be adapted. See the example below. Code: def maybe_async(fn): async def _process(fn, *args, **kwargs): coro_fn = fn(*args, **kwargs) if asyncio.iscoroutinefunction(fn): return await coro_fn else: return coro_fn @functools.wraps(fn) def wrapper(*args, **kwarg): loop = asyncio.get_event_loop() res = loop.run_until_complete(_process(fn, *args, **kwarg)) return res return wrapper Demo: @maybe_async async def agreet(delay): print("hello") await asyncio.sleep(delay) print("world") @maybe_async def greet(delay): print("hello") time.sleep(delay) print("world") agreet(2) # prints hello world after 2 seconds greet(1) # print hello world after 1 second Now you can call either sync or async functions like regular functions. Hope this helps. --- On Wed, Mar 6, 2019 at 12:54 AM Nathaniel Smith <n...@pobox.com> wrote: > Defining a single polymorphic function is easy at the library level. > For example, with asyncio: > > ---- > > def maybe_async(fn): > @functools.wraps(fn) > def wrapper(*args, **kwargs): > coro = fn(*args, **kwargs) > if asyncio.get_running_loop() is not None: > return coro > else: > return await coro > > @maybe_async > async def my_func(...): > ... use asyncio freely in here ... > > ---- > > You can't do it at the language level though (e.g. with your proposed > 'polymorph' keyword), because the language doesn't know whether an > event loop is running or not. > > Extending this from a single function to a whole library API is > substantially more complex, because you have to wrap every function > and method, deal with __iter__ versus __aiter__, etc. > > -n > > On Tue, Mar 5, 2019 at 8:02 PM Jorropo . <jorropo....@gmail.com> wrote: > > > > I was doing some async networking and I wondered, why I have to use 2 > different api for making the same things in async or sync regime. > > Even if we make 2 perfectly identical api (except function will be sync > and async), it will still 2 different code). > > > > So I first thinked to allow await in syncronous function but that create > some problems (ex: an async function calling async.create_task) so if we > allow that we have to asume to allways be in async regime (like js). > > > > Or we can differentiate async function wich can be awaited in syncronous > regime, maybe with a new keyword (here I will use polymorph due to a lack > of imagination but I find that one too long) ? > > > > So a polymorph function can be awaited in a syncronous function, and a > polymorph function can only await polymorph functions. > > > > Polymorph function work exacly like async function BUT they assure of > the ability to execute syncronously. > > And in a syncronous regime if an await need to wait (like async.sleep or > network operation), just wait (like the equivalent of this function in > syncronous way). > > > > So why made that ? > > To provide the same api for async and sync regime when its possible, > example http api. > > This allow to code less librairy. > > Syncronous users can just use the librairy like any other sync lib (with > the keyword await for executing but, personally, I think that is worth). > > And asyncronous users can run multiples tasks using the same lib. > > Moving from a regime to an other is simpler, source code size is reduced > (doesn't need to create 2 api for the same lib), gain of time for the same > reason. > > > > Also why it need to await in syncronous function, why not just execute > polymorph function like any sync function while called in a sync function ? > > Because we need to create runnable objects for async.run, ... > > > > So I would have your though about that, what can be improved, a better > name for polymorph ? > > _______________________________________________ > > Python-ideas mailing list > > Python-ideas@python.org > > https://mail.python.org/mailman/listinfo/python-ideas > > Code of Conduct: http://python.org/psf/codeofconduct/ > > > > -- > Nathaniel J. Smith -- https://vorpus.org > _______________________________________________ > Python-ideas mailing list > Python-ideas@python.org > https://mail.python.org/mailman/listinfo/python-ideas > Code of Conduct: http://python.org/psf/codeofconduct/ >
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/