Python TypeError:对象不可迭代,

Rod*_*her 4 python

我对 python 有点陌生,并尝试创建一个 DTO 来最大限度地减少从我的 api 公开的属性数量。我使用 Azure 表存储来获取记录,然后循环它以创建一个忽略属性的较小对象。虽然在这个过程中的某个地方我得到:“TypeError:'AbbreviatedPackage'对象不可迭代”

在我的主要内容中,我有以下调用:

@app.get("/list/")
def process_results(request: Request, x_api_key: str = Depends(X_API_KEY)):

    packageClient = QueryClient(az_connection_string, "appstoredev")
    results = packageClient.query_packages_storage("PartitionKey eq 'app'")

    return results
Run Code Online (Sandbox Code Playgroud)

query_packages_storage()

 def query_packages_storage(self, filter_query):
        from azure.data.tables import TableClient
        table_client = TableClient.from_connection_string(conn_str=self.connection_string, table_name=self.table_name)
        entities = table_client.query_entities(filter_query)

        json_entities = []
        for entity in entities:
            print(entity['ImageUrl'])
            filtered_entity = AbbreviatedPackage(
                entity['ImageUrl'],
                entity['PackageName'],
                entity['DisplayName'],
                entity['Summary']
            )

            json_entities.append(filtered_entity)

        return json.dumps(json_entities)
Run Code Online (Sandbox Code Playgroud)

缩写包类

class AbbreviatedPackage():

    def __init__(self, image_url, package_name, display_name, summary):
        self.imageUrl = image_url
        self.packageName = package_name
        self.displayName = display_name
        self.summary = summary
Run Code Online (Sandbox Code Playgroud)

当我调试 json_entitiesobject 时,它被正确填充 在此输入图像描述

任何帮助将不胜感激。干杯

** 编辑

我在循环中遇到错误 在此输入图像描述

INFO:     127.0.0.1:60027 - "GET /list/ HTTP/1.1" 500 Internal Server Error
ERROR:    Exception in ASGI application
Traceback (most recent call last):
  File "C:\source\IlionxCloud\iliona-store-packages\venv\lib\site-packages\uvicorn\protocols\http\h11_impl.py", line 373, in run_asgi
    result = await app(self.scope, self.receive, self.send)
  File "C:\source\IlionxCloud\iliona-store-packages\venv\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 75, in __call__
    return await self.app(scope, receive, send)
  File "C:\source\IlionxCloud\iliona-store-packages\venv\lib\site-packages\fastapi\applications.py", line 208, in __call__
    await super().__call__(scope, receive, send)
  File "C:\source\IlionxCloud\iliona-store-packages\venv\lib\site-packages\starlette\applications.py", line 112, in __call__
    await self.middleware_stack(scope, receive, send)
  File "C:\source\IlionxCloud\iliona-store-packages\venv\lib\site-packages\starlette\middleware\errors.py", line 181, in __call__
    raise exc
  File "C:\source\IlionxCloud\iliona-store-packages\venv\lib\site-packages\starlette\middleware\errors.py", line 159, in __call__
    await self.app(scope, receive, _send)
  File "C:\source\IlionxCloud\iliona-store-packages\venv\lib\site-packages\starlette\middleware\cors.py", line 84, in __call__
    await self.app(scope, receive, send)
  File "C:\source\IlionxCloud\iliona-store-packages\venv\lib\site-packages\starlette\exceptions.py", line 82, in __call__
    raise exc
  File "C:\source\IlionxCloud\iliona-store-packages\venv\lib\site-packages\starlette\exceptions.py", line 71, in __call__
    await self.app(scope, receive, sender)
  File "C:\source\IlionxCloud\iliona-store-packages\venv\lib\site-packages\starlette\routing.py", line 656, in __call__
    await route.handle(scope, receive, send)
  File "C:\source\IlionxCloud\iliona-store-packages\venv\lib\site-packages\starlette\routing.py", line 259, in handle
    await self.app(scope, receive, send)
  File "C:\source\IlionxCloud\iliona-store-packages\venv\lib\site-packages\starlette\routing.py", line 61, in app
    response = await func(request)
  File "C:\source\IlionxCloud\iliona-store-packages\venv\lib\site-packages\fastapi\routing.py", line 226, in app
    raw_response = await run_endpoint_function(
  File "C:\source\IlionxCloud\iliona-store-packages\venv\lib\site-packages\fastapi\routing.py", line 161, in run_endpoint_function
    return await run_in_threadpool(dependant.call, **values)
  File "C:\source\IlionxCloud\iliona-store-packages\venv\lib\site-packages\starlette\concurrency.py", line 39, in run_in_threadpool
    return await anyio.to_thread.run_sync(func, *args)
  File "C:\source\IlionxCloud\iliona-store-packages\venv\lib\site-packages\anyio\to_thread.py", line 28, in run_sync
    return await get_asynclib().run_sync_in_worker_thread(func, *args, cancellable=cancellable,
  File "C:\source\IlionxCloud\iliona-store-packages\venv\lib\site-packages\anyio\_backends\_asyncio.py", line 805, in run_sync_in_worker_thread
    return await future
  File "C:\source\IlionxCloud\iliona-store-packages\venv\lib\site-packages\anyio\_backends\_asyncio.py", line 743, in run
    result = func(*args)
  File "C:/source/IlionxCloud/iliona-store-packages/store-packages/main.py", line 49, in process_results
    results = packageClient.query_packages_storage("PartitionKey eq 'app'")
  File "C:\source\IlionxCloud\iliona-store-packages\store-packages\client\AzureTableEntityQueryClient.py", line 39, in query_packages_storage
    for entity in entities:
TypeError: 'AbbreviatedPackage' object is not iterable
Run Code Online (Sandbox Code Playgroud)

Jas*_*CFA 7

您的AbbreviatedPackage对象无法自动转换为 JSON。当您使用对象json.dumps列表运行AbbreviatedPackage时,默认情况下它们不应该是可序列化的,从而引发此错误(因为每个对象都试图迭代并且没有方法__iter__)。

几个选项:

  1. .__dict__附加到列表时,请使用对象的方法。我个人不喜欢这个解决方案,因为它是不受控制的。
  2. 编写__iter____str____repr__方法以正确序列化为 JSON 以及CustomEncoder属性的a json.dumps cls
# https://changsin.medium.com/how-to-serialize-a-class-object-to-json-in-python-849697a0cd3#8273

class Label:
    def __init__(self, label, x, y, width, height):
        self.label = label
        self.x = x
        self.y = y
        self.width = width
        self.height = height

    def __iter__(self):
        yield {
            "label": self.label,
            "x": self.x,
            "y": self.y,
            "width": self.width,
            "height": self.height
        }

    def __str__(self):
        return json.dumps(self, ensure_ascii=False, cls=CustomEncoder)

    def __repr__(self):
        return self.__str__()


Run Code Online (Sandbox Code Playgroud)

参考:https://changsin.medium.com/how-to-serialize-a-class-object-to-json-in-python-849697a0cd3#8273

还有CustomEncoder班级:

import json

class CustomEncoder(json.JSONEncoder):
    def default(
        self,
        o,
    ):
        """
        A custom default encoder.
        In reality this should work for nearly any iterable.
        """
        try:
            iterable = iter(o)
        except TypeError:
            pass
        else:
            return list(iterable)
        # Let the base class default method raise the TypeError
        return json.JSONEncoder.default(self, o)
Run Code Online (Sandbox Code Playgroud)

我用代码对此进行了完整的综合: