Python 中的抽象方法异步和同步实现

gil*_*iev 3 python asynchronous tornado mongoengine motorengine

假设我有BaseClass其中包含一些逻辑,其中和main_function()都是通用的。假设这两个类有其独特的实现,前者以同步方式实现,而后者以异步方式实现。我写了这样的东西,它似乎有效:SyncClassAsyncClassget_data()

class BaseClass:
    def get_data():
        pass

    @gen.coroutine
    def main_function():
        # some logic
        try:
            data = yield self.get_data()
        except:
            data = self.get_data()
        # some more logic

class SyncClass(BaseClass):
    def get_data():
        //makes sync call to Mongo and gets data (using Mongoengine)

class AsyncClass(BaseClass):
    @gen.coroutine
    def get_data():
        //makes async call to Mongo and gets data (using Motorengine)
Run Code Online (Sandbox Code Playgroud)

我使用此代码作为解决方法,因为我已经以这种方式实现了 get_data() 的这些方法。有一些更优雅的解决方案吗?我的代码有两部分与我有关:

try:
    data = yield self.get_data()
except:
    data = self.get_data()
Run Code Online (Sandbox Code Playgroud)

我不想在这里使用 try/ except 。

另一件事是:我@gen.coroutineAsyncClasswhile 中没有使用相同的函数进行@gen.coroutine装饰BaseClass

谢谢你!

Ben*_*ell 6

同步和异步方法具有不同的接口(这就是异步的含义)。AsyncClass.get_data返回一个Future; SyncClass.get_data才不是。如果这是在静态类型语言中,这两个方法将无法从基类实现相同的抽象方法。try/except当然,Python更灵活,不会以这种方式限制你,但是调用者仍然需要知道它正在处理哪种方法,或者准备好通过或isinstance检查等来查找(请注意,try / except是在这种情况下很危险,因为yield在龙卷风协程中会接受列表和字典之类的东西)

一般来说,您无法像您希望的那样在它们之间透明地切换。请记住,任何可能调用的函数yield self.get_data()也需要用 修饰@coroutine,因此一旦系统的一部分是异步的,它就会开始传播。通常最好接受这种趋势并使事情变得异步。