Python - перегрузка асинхронных методов - PullRequest
0 голосов
/ 22 сентября 2018

Я создаю оболочку для API.Пока это работает.Тем не менее, это синхронно, используя модуль запросов для HTTP-вызовов.

Я хотел бы реализовать способ асинхронного вызова этих методов без необходимости использовать другое имя или версию lib.Я сразу подумал о перегрузке, но, учитывая, что перегрузка в python немного отличается от других языков, это не выглядит реально возможным.

По сути, я хочу создать класс, который будет выглядеть следующим образом (идея -мудро, я знаю, что это не работает в Python):

class Foo:
    def foo(self):
        # Requests code...
        print("foo sync")

    async def foo(self):
        # aiohttp code...
        print("foo async")

И используйте это следующим образом:

f = Foo()
f.foo()
await f.foo()

Вывод:

>> "foo sync"
>> "foo async"

По сути, в этом коде асинхронная функция просто полностью переопределяет предыдущую, что на самом деле не помогает.

Из некоторого поиска в Google это выглядит не совсем возможным, однако Python всегда удается меня удивить.

Заранее спасибо: D

1 Ответ

0 голосов
/ 23 сентября 2018

Вопрос : перегрузка асинхронных методов

Рассмотрим следующие class определения, используя Inheritance с Overloading!

Youиметь базовую class Foo:, от которой наследуется class Foo_async(Foo):.
. Поэтому вы можете повторно использовать большую часть своей реализации в режимах sync и async.
class Foo_async в основном реализует только требования async/await.

Примечание : я использую asyncio.Например:

import asyncio

class Foo():
    def __init__(self):
        self.mode = "sync"

    def __repr__(self):
        return "{}::foo() {}".format(self.__class__.__name__, self.mode)

    def foo(self):
        print("{}".format(self.__repr__()))
        print("\t\tworkload {}".format(1))
        print("\t\tworkload {}".format(2))

class Foo_async(Foo):
    def __init__(self):
        self.mode = "async awaited"

    async def foo(self):
        super().foo()

Использование :

async def run(foo):
    await foo.foo()

if __name__ == '__main__':
    Foo().foo()

    loop = asyncio.get_event_loop()
    loop.run_until_complete(run(Foo_async()))
    loop.close()

Вывод :

Foo::foo() sync
        workload 1
        workload 2
Foo_async::foo() async awaited
        workload 1
        workload 2

Если вы хотите больше детализации, разделите рабочую нагрузку в def foo(...) на отдельные функции рабочей нагрузки.
Теперь вы можете вызывать эти функции, используя await.

Например: (Показать, только измененный код!)

class Foo():
    ...

    def foo(self):
        print("{}".format(self.__repr__()))
        self.workload_1()
        self.workload_2()

    def workload_1(self):
        print("\t\t{} workload {}".format(self.mode, 1))

    def workload_2(self):
        print("\t\t{} workload {}".format(self.mode, 2))

class Foo_async(Foo):
    ...       

    async def foo(self):
        print("{}".format(self.__repr__()))
        await self.workload_1()
        await self.workload_2()

    async def workload_1(self):
        super().workload_1()

    async def workload_2(self):
        super().workload_2()

Выход :

Foo::foo() sync
        sync workload 1
        sync workload 2
Foo_async::foo() async awaited
        async awaited workload 1
        async awaited workload 2

Протестировано с Python: 3.5.3

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...