Timeouts and Cancellations for Humans

说明: 原文出处Timeouts and cancellation for humans — njs blog (vorpus.org)。 译者以已经获得了原作者的允许以翻译该文章。 本文原作者为Nathaniel J. Smith,Trio库的作者,NumPy, PyPa相关项目的代码贡献者。 术语翻译说明:翻译内容可能混用,函数参数名会保留英文,常见词(如bug)不翻译。 primitive: 原语、底层函数 cancel scope: 取消域 cancel token: 取消令牌 timeout: 超时 deadline: 大家很习惯且考虑到翻译成截止时间比较啰嗦就不做翻译了。 shield: 没有想好如何翻译,就没有做翻译。 nursery: Trio中的一个启动子任务的系统,翻译成托儿所有点傻,就未做翻译。 其他翻译:见翻译说明 本文评论使用的是disqus 引言 你的代码可能完美无缺,但不幸的是外面的世界并不这么靠谱。有些时候,其他人的代码可能会崩溃或者卡住。网络会掉线,打印机会报错。你的代码也需要为这些情况做好准备。每当你从网络读取数据、尝试获取跨进程锁、或者发送一条HTTP请求,你至少要考虑到以下三种可能: 请求可能成功 请求可能失败 请求可能挂起。春去秋来,没有成功,没有失败,没有任何响应。 前面两种情况非常直观。最后一种情况你需要使用超时来处理。几乎每一处你与其他进程、系统通信的地方都需要设置超时,如果你没有设置超时,那就是一个潜在的bug。 说实话,如果你也像大多数开发者一样,那么你的代码可能会有很多因为缺失超时导致的bug,我的代码也是这样的。因为正确进行I/O操作非常常见且重要,你可能觉得任何一种编程环境都能为所有操作提供简单而健壮的设置超时的方法。但奇怪的是,事实并不如此。大多数带超时的API都非常单调且容易出错,以至于要求开发人员把这些弄对是不切实际的。所以别难过,你的代码有这些超时相关的bug并不是你的错,而是那些I/O库的错! 我目前正在写一个I/O库。和其他任何I/O库都不一样,这个I/O库的所有卖点是它痴迷于简单易用。我想让你能够在使用Trio时,能够简单而又正确地对任意I/O操作应用超时。但是,用户友好的超时API是一件很棘手的事。所以我会在这篇博客中深入讨论各种可能的设计,特别是那些给我提供灵感的设计。接下来我会介绍我想到的设计,以及为什么我会认为该设计是古老的”状态艺术”的一个切实优化。最后,我将会讨论为什么Trio库的思路为适应面更广,同时我将会给出一个不错的同步Python的原型实现。 那么超时处理有什么难的呢? 目录: 简单的超时机制不支持抽象 绝对的deadline是可组合的(但是用起来很麻烦) 取消令牌(Cancel tokens) 取消令牌封装了取消状态 取消令牌属于水平触发,可以根据你程序的需要来确定范围 实际上因为人类的懒惰取消令牌并不可靠 取消域: Trio关于超时和取消的人性化方案 取消域(Cancel scope)是如何工作的 我们需要在哪些地方检查取消? 一个逃逸口(escape hatch) 取消域与并发 小结 还有哪些地方可以从取消域中受益? 同步、单线程Python asyncio 其他语言 现在去修复你的超时bug! 注释 翻译说明 简单的超时机制不支持抽象 最简单的处理超时的方式无疑是给每个可能阻塞的函数加上timeout参数。在Python标准库中,你可以找到像threading....

February 7, 2023 · Author Nathaniel J. Smith, translated by Dennis

使用Cython实现Python Bindings

背景 语言交互接口(FFI) 一般操作系统会提供系统调用的C API。这种说法其实并不正确,但是我们假设这个说法是正确的。毕竟很多Linux发行版都是自带了GCC编译器的,我们就简单的认为提供了系统调用的C API。然后我们思考一下这么一个问题,一个非C语言是怎么实现和操作系统交互的?主要有两种方式实现,一种是使用中断来实现系统调用,另外一种方式是间接使用C语言的系统调用API。 间接调用C语言的API涉及到了语言交互接口(FFI, Foreign Function Interface)的概念。不少编程语言就通过使用FFI来实现系统调用。很多语言把FFI叫做"Language Bindings”,比如Python Bindings。还有一些语言有自己的叫法,比如Java的JNI。通过使用FFI,像Python这些语言就可以比较简单的实现系统调用。 Python Bindings Python Bindings可以让Python代码调用C API,或者在C程序中运行Python脚本。实现Python Bindings有两种基本的方式,分别如下: 使用Python的标准库ctypes 使用CPython提供的库Python/C API 和很多基础库一样,这两个库都很底层,在业务代码中使用起来会比较复杂。我们可以用一些封装好的三方库来实现Python Bindings,比如使用Cython。 使用Cython实现Python Bindings Cython简介 Cython是一种能够方便为Python编写C扩展的编程语言,其编译器可以将Cython代码编译为C代码。Cython兼容Python的所有语法且能编译成C,故Cython可以允许开发者通过Python式的代码来手动控制GIL。Cython其语法也允许开发者方便的使用C/C++代码库。通过以下命令即可安装Cython。 1 pip install Cython Cython基础使用方法 Hello, World! 所有合法的Python语法都是合法的Cython语法,我们先写一个简单的例子保存到hello.pyx。 1 2 3 # hello.pyx def say_hello_to(name): print("Hello %s" % name) 接着写一下setup文件来编译和构建这个扩展。 1 2 3 4 5 6 7 # setup.py from setuptools import setup from Cython.Build import cythonize setup( ext_modules = cythonize("hello....

August 10, 2022 · Dennis Xie