Существуют ли асин c абстрактные базовые классы в Python 3? - PullRequest
1 голос
/ 25 апреля 2020

Мне нужно реализовать тип отображения в приложении asyn c Python 3 (я использую tornadoweb, но это может быть любое событие l oop.)

Я хотел бы принять преимущество пакета collections.abc. При отображении следует использовать mongodb (точнее, Motor https://motor.readthedocs.io/en/stable/) для хранения пар ключ-значение.

Моя проблема в том, что MutableMapping не имеет версии ayn c. Например:

from collections.abc import MutableMapping
class AsyncMongoMap(MutableMapping):
    async def __getitem__(self, key):
        return await self.collection.find_one(dict(key=key))["value"]

Теоретически все абстрактные методы (__getitem__, __setitem__, __delitem__, __iter__ and __len__) могут быть асин c методами, возвращающими ожидаемые объекты. Это позволило бы мне ждать их, например:

await some_map["key"]

Проблема в том, что __getitem__ не может быть асинхронным c методом. Я все еще могу вернуть ожидаемое от него, но это не поможет. Он не совместим с MutableMapping. Например, метод get() ожидает, что getitem вызовет KeyError, когда ключ отсутствует в отображении. Так что если __getitem__ вернет ожидаемое, то get() просто не будет работать (и его все равно нельзя ожидать). Так что это никогда не сработает:

await some_map.get("key", "default_value")

Хорошим решением было бы использовать collections.abc.AsyncMutableMapping, если бы была такая вещь. Я мог бы написать свою собственную версию, но это кажется плохой идеей. Это общая проблема, связанная с отсутствием асин c версий абстрактных базовых классов.

Существует ли для этого "наилучшая практика"? Должен ли я написать и опубликовать sh новый пакет для реализации абстрактных базовых классов asyn c? Или, может быть, в Python уже есть что-то для этого, просто я не знаю об этом?

1 Ответ

0 голосов
/ 25 апреля 2020

То, что я хотел, невозможно, потому что для него отсутствует синтаксис языка.

Существует синтаксис для await some_map["key"] или await some_map.get("key", default_value), но он никогда не будет работать для них:

del some_map["key"] # del is a keyword, cannot await
some_map["key"] = value # assignment is a syntax, but there is no syntax to await for it

Так что в принципе то, что я хочу, невозможно, поскольку синтаксис отсутствует в языке , Я должен реализовать это с помощью обычных методов и, возможно, реализовать некоторые более сложные методы, которые можно использовать с имеющимся на данный момент синтаксисом - но даже тогда это может быть плохой идеей, потому что IDE и программы инспектора кода, вероятно, никогда не будут жаловаться на отсутствующие ожидания и вводить ошибок. Например, когда get () является асинхронным методом c, инспектор кода может предупредить об этом:

# warning: # some_dict.get() was never awaited for
return some_dict.get("key") 

Однако он никогда не будет жаловаться на это:

# this is not a method call, no warning issued
return some_dict["key"]
...