- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
__exit__
的正确类型签名是什么?我有以下内容:
from types import TracebackType
from typing import Optional, Type
class Foo:
def __enter__(self) -> 'Foo':
return self
def __exit__(self, exc_type: Optional[Type[BaseException]],
exc_value: Optional[BaseException],
traceback: Optional[TracebackType]) -> bool:
return False
在最近的 mypy (0.560) 上,它使用 --strict
进行类型检查(我对这个签名有一定的信心,因为我从类型库的内部偷走了它)。
当此脚本使用 python 3.6 运行时,正如预期的那样没有任何反应。但是当使用 3.5.2 运行时,我们得到一个异常:
Traceback (most recent call last):
File "/home/student/mypy_test/test.py", line 4, in <module>
class Foo: #(ContextManager['Foo']):
File "/home/student/mypy_test/test.py", line 8, in Foo
def __exit__(self, exc_type: Optional[Type[BaseException]],
File "/usr/lib/python3.5/typing.py", line 649, in __getitem__
return Union[arg, type(None)]
File "/usr/lib/python3.5/typing.py", line 552, in __getitem__
dict(self.__dict__), parameters, _root=True)
File "/usr/lib/python3.5/typing.py", line 512, in __new__
for t2 in all_params - {t1} if not isinstance(t2, TypeVar)):
File "/usr/lib/python3.5/typing.py", line 512, in <genexpr>
for t2 in all_params - {t1} if not isinstance(t2, TypeVar)):
File "/usr/lib/python3.5/typing.py", line 1077, in __subclasscheck__
if super().__subclasscheck__(cls):
File "/home/student/.local/share/virtualenvs/sf_cs328-crowdsourced-QAuuIxFA/lib/python3.5/abc.py", line 225, in __subclasscheck__
for scls in cls.__subclasses__():
TypeError: descriptor '__subclasses__' of 'type' object needs an argument
如果去掉参数直到异常消失,我们发现问题类型是第一个:exc_type: Optional[Type[BaseException]]
。
注意:如果类型签名不匹配(使用 mypy 运行时),要让它发出提示,您需要将 class Foo:
更改为 class Foo(ContextManager['Foo'])
。我没有在代码片段中这样做,因为 Python 3.5.2 中的 typing
缺少 Coroutine
、Awaitable
、ContextManager
等(这是旧发行版的 LTS 版本中的版本)。我在这里写了一个解决方法:https://stackoverflow.com/a/49952293/568785 .所以我想,完整的可重现示例是:
# Workaround for ContextManager missing in 3.5.2 typing
from typing import Any, TypeVar, TYPE_CHECKING
try:
from typing import ContextManager
except ImportError:
class _ContextManager:
def __getitem__(self, index: Any) -> None:
return type(object())
if not TYPE_CHECKING:
ContextManager = _ContextManager()
# The actual issue:
from types import TracebackType
from typing import Optional, Type
class Foo:
def __enter__(self) -> 'Foo':
return self
def __exit__(self, exc_type: Optional[Type[BaseException]],
exc_value: Optional[BaseException],
traceback: Optional[TracebackType]) -> bool:
return False
我已经验证不继承 ContextManager
在 Python 3.5.2 中运行仍然会产生错误(所以这个异常不是这个 hack 的产物,它是 3.5.2 的产物运行时的类型库不喜欢 __exit__
的签名)。
据推测,这是 Python 3.5 的 typing
库中的另一个错误。有解决这个问题的明智方法吗?
最佳答案
我现在使用的一个丑陋解决方法是使用TYPE_CHECKING
来确定我是否应该伪造类型:
from typing import Type, TYPE_CHECKING
if TYPE_CHECKING:
BaseExceptionType = Type[BaseException]
else:
BaseExceptionType = bool # don't care, as long is it doesn't error
然后你可以这样做:
def __exit__(self, exc_type: Optional[BaseExceptionType],
exc_value: Optional[BaseException],
traceback: Optional[TracebackType]) -> bool:
return False
已针对 Python 3.5.2 和 mypy 0.560 进行验证。
这当然会破坏任何 RTTI,但 AFAIK RTTI 是 PEP 的一部分,直到 3.6 或 3.7 才(实验性地)登陆。不过,这显然会破坏 typing.get_type_hints()
。
关于python - 在 3.5 中键入 __exit__ 在运行时失败,但类型检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49959656/
是否有一种 Pythonic 的方式来自动 __exit__ 一个类的所有成员? class C: def __init__(self): self.a = open('foo
我明白了 __enter__ 和__exit__ 用于实现上下文管理器。 如果在 with 语句中发生异常,异常的类型、值和回溯将传递给 __exit__ 方法。 __exit__ 可以处理异常: 返
我尝试从以下位置运行示例:https://docs.python.org/3/library/socketserver.html#socketserver-tcpserver-example 在我的笔
我无法在测试中将 __exit__ 方法附加到 mockito 模拟,以便模拟在 with 语句中使用它时不会介意。 这是一个不断引发 AttributeError: __exit__: 的测试示例
我在提醒自己“关键字”时偶然发现了这篇文章 http://effbot.org/zone/python-with-statement.htm 。我只是有一个小问题,可能是显而易见的问题。文章指出,这“
我已经通过.csv文件来发布请求, input_file = data.get('file', None) with input_file as datasheet: header =
调查 documentation python 中的 with 语句: The context manager’s __exit__() method is invoked. 我想知道如果我这样做会发
考虑到这个小的 Python 类,每当我使用 Ctrl+C 停止脚本时,__exit__ 函数都会在引发异常之前运行: import time class MyClass(object): d
一些背景:我在一家大银行工作,我试图重新使用一些 Python 模块,我无法更改,只能导入。我也没有安装任何新实用程序/功能等的选项(在 Linux 上运行 Python 2.6)。 我目前有这个:
我正在制作类似任务调度程序的东西,使用生成器作为协程。在下面的代码中,我需要确定性地执行 print cleanup。 从我的交互看来,将对象释放给垃圾收集器会导致上下文管理器退出。但是,我知道最好不
我知道从上下文管理器的 __exit__() 方法中重新引发异常是不好的风格。因此,我想在实例上附加一个属性,该属性可以携带上下文信息,如果我让异常通过或捕获它,则该信息不可用。这将避免重新提高它。
考虑以下 Python 2.x 代码片段。 from __future__ import print_function class myfile(file): def __exit__(sel
使用 pool.map(funct, iterable) 时出现此错误: AttributeError: __exit__ 没有解释,只是堆栈跟踪到模块内的 pool.py 文件。 这样使用: wit
我最近想知道当 __enter__ 引发异常时不隐式调用 __exit__ 的原因是什么?为什么要这样设计?我正在实现服务运行器类以供 'with' 关键字使用,结果 __exit__ 从未被调用。
鉴于以下 ContextManager类,这里是 __exit__ 的顺序以下示例中的调用 - 声明的相反顺序。 有趣的是,__exit__可以多次调用。这在 2.7 的所有 Python 版本中都是
我是单元测试的新手,我正在尝试找到一种方法来测试 with 关键字是否在我的对象中正常工作。 在这种情况下,我的对象有一个创建临时目录的 __enter__ 方法和应该销毁它的 __exit__ 方法
类有一个可定义的函数__exit__,允许实现上下文管理器。 它接受必需的参数: def __exit__(self, exc_type, exc_val, exc_tb): 但我找不到关于这些参数是
如果它引发异常(可能多次,可能有延迟),我想在 exit() 方法中再次调用代码对象。我知道使用装饰器很容易做到,但我的动机是有时我只想重复一些我不想提取到单独函数并装饰它的代码片段。我正在寻找这些方
当使用不带 as 的 with 语句时,__enter__ 函数永远不会执行,但 __exit__方法会? 例子: with test: test.do_something test.__exit
我正在尝试使用 Mock 修补一些上下文管理器功能,以便我可以测试代码在给定好的、坏的和垃圾输入的情况下是否能做出明智的事情。这是带有 with 语句的测试代码。补丁已在我的代码中的正确位置完成。 @
我是一名优秀的程序员,十分优秀!