1

我是异步 python 的新手。

我创建了一个应该从文件系统加载文件的单例对象

class AppResourceLoader(metaclass=Singleton):
    async def load_yaml(self, resource_filepath):
        async with open(path.join(path.dirname(path.dirname(__file__)), 'resources', resource_filepath)) as f:
            return await yaml.safe_load(f.read())

Singleton是一个普通的元类

class Singleton(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(
                Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

我使用它AppResourceLoader在类构造函数中上传文件并稍后通过getter访问它

class ServiceCatalog(metaclass=Singleton):
    def __init__(self, catalog_file):
        self.services = AppResourceLoader().load_yaml(catalog_file)

    def get_catalog(self):
        return self.services

这个get_catalog方法我在另一个类中调用

class ServiceBrokerController(metaclass=Singleton):
    def __init__(self):
        self.catalog = ServiceCatalog('catalog.yml')

    @ujson_route
    def get_catalog(self):
        return self.catalog.get_catalog()

装饰ujson_route器看起来像这样

def ujson_route(func):
    async def wrapper(*args, **kwargs):
        return UJSONResponse(func(args[0]))
    return wrapper

这个get_catalog函数ServiceBrokerController被 Starlette 路由对象使用

async def on_startup_upload_catalog(request):
    ServiceBrokerController()

app = Starlette(
    debug=True,
    routes=[
        Route('/v2/catalog', ServiceBrokerController().get_catalog)],
    exception_handlers=exceptions.exception_handler,
    on_startup=[]
)

我运行测试get_catalog看起来像这样

def test_catalog():
    with TestClient(app) as client:
        response = client.get('/v2/catalog')
        assert response.status_code == 200

        services = ujson.loads(response.content)
        expected_services = AppResourceLoader().load_yaml('catalog.yml')

        # no changes
        assert deepdiff.DeepDiff(services, expected_services) == {}

但是当我使用plain执行测试时pytest -v,它失败并出现错误

self = <starlette.responses.UJSONResponse object at 0x102d8f990>, content = <coroutine object AppResourceLoader.load_yaml at 0x102c8b9e0>

def render(self, content: typing.Any) -> bytes:
        assert ujson is not None, "ujson must be installed to use UJSONResponse"
>       return ujson.dumps(content, ensure_ascii=False).encode("utf-8")
E       TypeError: <coroutine object AppResourceLoader.load_yaml at 0x102c8b9e0> is not JSON serializable

在我使load_yaml方法异步之前它起作用了。

怎么了?据我了解,我需要放在await某个地方,因为据我了解,从错误中它返回协程而不是文件数据。

4

0 回答 0