TypeError: issubclass()的第一个参数必须是一个类,而我非常确定第一个参数是一个类。

4

我的代码中有如下代码行。

from inspect import isclass

if isclass(route.handler) and issubclass(route.handler, web.View):

很不幸,这一行代码在我的生产环境中会引发以下异常。

TypeError: issubclass() arg 1 must be a class

据我所知,Python(3.7.7)编译器将首先检查if语句的第一个条件,如果评估为false,则不会检查第二个条件。因此,我必须得出结论,route.handler必须是一个类,因此我所遇到的TypeError不应该发生。这里是否有什么漏洞呢?是否有人知道可能导致这种情况的原因吗?
(不幸的是,我无法重现这个错误)
编辑:
错误源于swagger-aiohttp包。以下是完整的traceback:
Traceback (most recent call last):
  File "/var/www/app/main.py", line 249, in <module>
    run_app(cfg)
  File "/var/www/app/main.py", line 225, in run_app
    setup_swagger(app, ui_version=SWAGGER_VERSION, swagger_url=SWAGGER_URL)
  File "/home/webapp/.venv/lib/python3.7/site-packages/aiohttp_swagger/__init__.py", line 72, in setup_swagger
    security_definitions=security_definitions
  File "/home/webapp/.venv/lib/python3.7/site-packages/aiohttp_swagger/helpers/builders.py", line 163, in generate_doc_from_each_end_point
    end_point_doc = _build_doc_from_func_doc(route)
  File "/home/webapp/.venv/lib/python3.7/site-packages/aiohttp_swagger/helpers/builders.py", line 44, in _build_doc_from_func_doc
    if isclass(route.handler) and issubclass(route.handler, web.View):
  File "/home/webapp/.venv/lib/python3.7/abc.py", line 143, in __subclasscheck__
    return _abc_subclasscheck(cls, subclass)
TypeError: issubclass() arg 1 must be a class

编辑2:

route.handler 应该是一个 aiohttp 基于类的视图。例如,这是如何创建并在其上构建一个 swagger UI 的示例。

class PingHandler(web.View):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    async def get(request):
        """
        ---
        description: This end-point allow to test that service is up.
        tags:
        - Health check
        produces:
        - text/plain
        responses:
            "200":
                description: successful operation. Return "pong" text
            "405":
                description: invalid HTTP Method
        """
        return web.Response(text="pong")

app = web.Application()
app.router.add_route('GET', "/ping", PingHandler)

setup_swagger(app, swagger_url="/api/v1/doc", ui_version=3)

在我目前的实现中,我还向Handler类添加了一个装饰器。

编辑3:

在本地调试时(工作正常),route.handler 似乎是 <class 'abc.ABCMeta'> 类型。


2
请问您能否发布完整的回溯信息?“route”和“route.handler”是什么? - MisterMiyagi
2
请告诉我们 route.handler 到底是什么。它似乎是一个通过了 isclass 测试的对象,但不足以通过 issubclass,因此我们需要一些关于这个神秘对象的详细信息。 - deceze
1
远程/本地机器上的Python版本是否相同? - Carlo Zanocco
1
@CarloZanocco 谢谢,我也发现了这个问题,我相信他们通过添加 isclass 检查来修复了这个问题。仍然想知道一个类如何通过 isclass 检查,但在评估 issubclass 检查时仍会导致 TypeError。 - Daan Klijn
1
你可以尝试在远程机器上编辑模块代码,并将issubclass替换为isinstanceissubclass需要一个类,而另一个需要一个对象。isclass需要一个对象,我认为问题就出在这里。这可以解释为什么isclass测试通过,而另一个会抛出异常。但它并不能解释为什么在你的本地机器上仍然能够正常工作。 - Carlo Zanocco
显示剩余7条评论
1个回答

2

我终于发现了问题所在。每当使用wrapt库的装饰器与abc.ABCMeta类一起使用时,就会引发错误。这是目前wrapt库的一个未解决问题。下面是一个示例:

import abc
from inspect import isclass
import wrapt

class Base:
    pass

class BaseWithMeta(metaclass=abc.ABCMeta):
    pass

@wrapt.decorator
def pass_through(wrapped, instance, args, kwargs):
    return wrapped(*args, **kwargs)


@pass_through
class B(BaseWithMeta):
    pass

@pass_through
class C(Base):
    pass


isclass(C)
>>>
True

issubclass(C, Base)
>>>
True

isclass(B)
>>>
True

issubclass(B, BaseWithMeta)
>>>
TypeError: issubclass() arg 1 must be a class


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接