如何正确在`QRunnable`类中使用`pyqtSlot()`装饰器为函数添加类型提示?

huangapple go评论129阅读模式
英文:

How to correctly type-hint a function with `pyqtSlot()` decorator inside `QRunnable` class?

问题

  1. **状态**:
  2. 1. 我正在学习如何在`PyQt`库中使用并发/线程,来自[www.pythonguis.com][1]。下面是来自此教程的简化/部分代码。
  3. 2. 我希望在我的代码中使用严格的类型提示。但我从`mypy`得到了关于此代码的错误消息(显示在第二个源代码块中)。
  4. **问题**:
  5. - 在使用`pyqtSlot()`装饰器时,如何正确地给函数添加类型提示?
  6. - `Superclass`(返回`None`)是什么,`Subclass`(返回`str|None`)在这种情况下是什么?
  7. **我尝试解决的问题**:
  8. - 我的自闭症使我无法接受在我的文本编辑器上显示错误。我浪费了太多时间来解决单行问题。我在互联网上找不到任何有用的信息。
  9. - 定义(或者我应该说是`stub`文件)中说`pyqtSlot()`是:
  10. `def pyqtSlot(*types, name: typing.Optional[str] = ..., result: typing.Optional[str] = ...) -> typing.Callable[..., typing.Optional[str]]: ...`,由于我对装饰器没有经验,无法解释这个。
  11. - `stub`文件:`QtCore.pyi`中说`Class QRunnable`的`run`是:`def run(self) -> None: ...`。
  1. $ mypy /tmp/tmp.py
  2. /tmp/tmp.py:22: error: run”的签名与超类型“QRunnable”不兼容 [override]
  3. /tmp/tmp.py:22: note: 超类:
  4. /tmp/tmp.py:22: note: def run(self) -> None
  5. /tmp/tmp.py:22: note: 子类:
  6. /tmp/tmp.py:22: note: str | None
  7. 1 个文件中找到 1 个错误(共检查了 1 个源文件)

编辑

  • 以下猜测是否正确?

    • pyqtSlot()接受返回typing.Optional[str](即str | None)的函数。也许这是“子类”?
    • QRunnable的方法run()只返回None。也许这是“超类”?
    • 在这种情况下,正确的问题是:如果“装饰器的返回值”和“函数的返回值”不同,如何使用装饰器?这是否是正确的问题?
  1. <details>
  2. <summary>英文:</summary>
  3. **Status**:
  4. 1. I&#39;m learning how to use concurrency/threads within `PyQt` library from here [www.pythonguis.com][1]. Below is the simplified/part of code from this tutorial.
  5. 2. I want strict type hinting in my code. And I&#39;m getting error messages on this code from `mypy`. (Shown on the 2-nd source-code block).
  6. **Question**:
  7. - How to correctly type-hint the function while using `pyqtSlot()` decorator?
  8. - What is `Superclass` (that return `None`), and what is `Subclass` (that returns `str|None`) in this case?
  9. **What I tried to solve:**
  10. - My autistic ass doesn&#39;t sit well with error is showing on my text-editor. And I wasted too much time to solve single line. I couldn&#39;t find anything useful on the internet.
  11. - The definition (or should I say `stub` file) says `pyqtSlot()` is:
  12. `def pyqtSlot(*types, name: typing.Optional[str] = ..., result: typing.Optional[str] = ...) -&gt; typing.Callable[..., typing.Optional[str]]: ...`, I&#39;m unable to interpret this due to no-experience on decorators.
  13. - `stub` file: `QtCore.pyi` says that `Class QRunnable`&#39;s `run` is: `def run(self) -&gt; None: ...`.
  14. ```lang-python
  15. from typing import Callable
  16. from PyQt5.QtCore import QObject, QRunnable, pyqtSignal, pyqtSlot
  17. import traceback
  18. import sys
  19. class WorkerSignal(QObject):
  20. finished = pyqtSignal()
  21. error = pyqtSignal(tuple)
  22. result = pyqtSignal(object)
  23. progress = pyqtSignal(int)
  24. class Worker(QRunnable):
  25. def __init__(self, fn: Callable[[], str]) -&gt; None:
  26. super(Worker, self).__init__()
  27. self.fn:Callable[[], str] = fn
  28. self.signals: WorkerSignal = WorkerSignal()
  29. @pyqtSlot()
  30. def run(self) -&gt; None: # &lt;====================== this line
  31. try:
  32. result: str = self.fn()
  33. except Exception:
  34. traceback.print_exc()
  35. exctype, value = sys.exc_info()[:2]
  36. self.signals.error.emit((exctype, value, traceback.format_exc()))
  37. else:
  38. self.signals.result.emit(result)
  39. finally:
  40. self.signals.finished.emit()
  1. $ mypy /tmp/tmp.py
  2. /tmp/tmp.py:22: error: Signature of &quot;run&quot; incompatible with supertype &quot;QRunnable&quot; [override]
  3. /tmp/tmp.py:22: note: Superclass:
  4. /tmp/tmp.py:22: note: def run(self) -&gt; None
  5. /tmp/tmp.py:22: note: Subclass:
  6. /tmp/tmp.py:22: note: str | None
  7. Found 1 error in 1 file (checked 1 source file)

EDIT:

  • Is the following guess correct?

    • pyqtSlot() takes function that returns typing.Optional[str] (i.e. str | None). Perhaps its the subclass?
    • QRunnable's method run() only return None, Perhaps it's the superclass?
    • In this case, correct question would be: How to use decorator, if decorator&#39;s return and function&#39;s return are different? Would this be the correct question?

答案1

得分: 2

除了类型提示,你不应该在QRunnable方法中使用pyqtSlot。

pyqtSlot装饰器仅在继承自QObject的类的方法中使用,而QRunnable不是。我已经审查了几个教程,它们诉诸于这种不好的实践,因为它不带来任何好处。

英文:

Other than the typehint you should not use pyqtSlot in a QRunnable method.

The pyqtSlot decorator is only used in methods of classes that inherit from QObject and QRunnable is not. I have reviewed several tutorials that resort to this bad practice since it does not bring any benefit.

huangapple
  • 本文由 发表于 2023年8月9日 09:45:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/76864077-2.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定