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

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

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

问题

**状态**:
1. 我正在学习如何在`PyQt`库中使用并发/线程,来自[www.pythonguis.com][1]。下面是来自此教程的简化/部分代码。
2. 我希望在我的代码中使用严格的类型提示。但我从`mypy`得到了关于此代码的错误消息(显示在第二个源代码块中)。

**问题**:
- 在使用`pyqtSlot()`装饰器时,如何正确地给函数添加类型提示?
- `Superclass`(返回`None`)是什么,`Subclass`(返回`str|None`)在这种情况下是什么?

**我尝试解决的问题**:
- 我的自闭症使我无法接受在我的文本编辑器上显示错误。我浪费了太多时间来解决单行问题。我在互联网上找不到任何有用的信息。
- 定义(或者我应该说是`stub`文件)中说`pyqtSlot()`是:
`def pyqtSlot(*types, name: typing.Optional[str] = ..., result: typing.Optional[str] = ...) -> typing.Callable[..., typing.Optional[str]]: ...`,由于我对装饰器没有经验,无法解释这个。
- `stub`文件:`QtCore.pyi`中说`Class QRunnable`的`run`是:`def run(self) -> None: ...`。
$ mypy /tmp/tmp.py
/tmp/tmp.py:22: error: “run”的签名与超类型“QRunnable”不兼容  [override]
/tmp/tmp.py:22: note:      超类:
/tmp/tmp.py:22: note:          def run(self) -> None
/tmp/tmp.py:22: note:      子类:
/tmp/tmp.py:22: note:          str | None
在 1 个文件中找到 1 个错误(共检查了 1 个源文件)

编辑

  • 以下猜测是否正确?

    • pyqtSlot()接受返回typing.Optional[str](即str | None)的函数。也许这是“子类”?
    • QRunnable的方法run()只返回None。也许这是“超类”?
    • 在这种情况下,正确的问题是:如果“装饰器的返回值”和“函数的返回值”不同,如何使用装饰器?这是否是正确的问题?

<details>
<summary>英文:</summary>

**Status**: 
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.
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).

**Question**:
- How to correctly type-hint the function while using `pyqtSlot()` decorator? 
- What is `Superclass` (that return `None`), and what is `Subclass` (that returns `str|None`) in this case?

**What I tried to solve:**
- 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. 
- The definition (or should I say `stub` file) says `pyqtSlot()` is: 
`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.
- `stub` file: `QtCore.pyi` says that `Class QRunnable`&#39;s `run` is: `def run(self) -&gt; None: ...`.


```lang-python
from typing import Callable
from PyQt5.QtCore import QObject, QRunnable, pyqtSignal, pyqtSlot

import traceback
import sys


class WorkerSignal(QObject):
    finished = pyqtSignal()
    error = pyqtSignal(tuple)
    result = pyqtSignal(object)
    progress = pyqtSignal(int)


class Worker(QRunnable):
    def __init__(self, fn: Callable[[], str]) -&gt; None:
        super(Worker, self).__init__()
        self.fn:Callable[[], str] = fn
        self.signals: WorkerSignal = WorkerSignal()

    @pyqtSlot()
    def run(self) -&gt; None:   # &lt;====================== this line
        try:
            result: str = self.fn()
        except Exception:
            traceback.print_exc()
            exctype, value = sys.exc_info()[:2]
            self.signals.error.emit((exctype, value, traceback.format_exc()))
        else:
            self.signals.result.emit(result)
        finally:
            self.signals.finished.emit()
$ mypy /tmp/tmp.py
/tmp/tmp.py:22: error: Signature of &quot;run&quot; incompatible with supertype &quot;QRunnable&quot;  [override]
/tmp/tmp.py:22: note:      Superclass:
/tmp/tmp.py:22: note:          def run(self) -&gt; None
/tmp/tmp.py:22: note:      Subclass:
/tmp/tmp.py:22: note:          str | None
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:

确定