- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我们有一个使用 asyncio 和协程(async
方法和 await
s)的 python 代码库,我想做的是调用一个这些方法来自已被拉入 python 的 C++ 类(使用 pybind11)
假设有这段代码:
class Foo:
async def bar(a, b, c):
# some stuff
return c * a
假设代码是从 python 调用的,并且有一个 io 循环处理这个,在某个时候,代码会进入 C++ 领域,在那里需要调用这个 bar
方法 - 如何await
这个在 C++ 中的结果?
最佳答案
用 C++ 实现 Python 协程是可能的,但需要一些工作。您需要执行解释器(编译器在静态语言中)通常为您执行的操作,并将您的异步函数转换为状态机。考虑一个非常简单的协程:
async def coro():
x = foo()
y = await bar()
baz(x, y)
return 42
调用 coro()
不会运行它的任何代码,但它会生成一个 awaitable 对象,该对象可以多次启动然后恢复。 (但您通常不会看到这些操作,因为它们是由事件循环透明地执行的。)可等待对象可以以两种不同的方式响应:1) 挂起,或 2) 指示它已完成。
在协程内 await
实现暂停。如果协程是用生成器实现的,y = await bar()
会脱糖到:
# pseudo-code for y = await bar()
_bar_iter = bar().__await__()
while True:
try:
_suspend_val = next(_bar_iter)
except StopIteration as _stop:
y = _stop.value
break
yield _suspend_val
换句话说,await
会挂起(让出)只要等待的对象还在。等待的对象通过引发 StopIteration
并通过在其 value
属性中走私返回值来表示它已完成。如果 yield-in-a-loop 听起来像 yield from
,那您就完全正确了,这就是为什么 await
经常被用术语描述的原因 yield 来自
。但是,在 C++ 中我们没有 yield
( yet ),因此我们必须将上述内容集成到状态机中。
要从头开始实现async def
,我们需要一个满足以下约束的类型:
__await__
方法,它可以只是self
;__iter__
,它又可以是self
;__next__
方法,其调用实现了状态机的一个步骤,返回表示暂停,引发 StopIteration
表示完成。__next__
中上述协程的状态机将由三个状态组成:
foo()
同步函数时bar()
协程时的下一个状态,只要它挂起(传播挂起)给调用者。一旦 bar()
返回一个值,我们可以立即继续调用 baz()
并通过 StopIteration
异常返回该值。所以上面显示的 async def coro()
定义可以被认为是以下语法糖:
class coro:
def __init__(self):
self._state = 0
def __iter__(self):
return self
def __await__(self):
return self
def __next__(self):
if self._state == 0:
self._x = foo()
self._bar_iter = bar().__await__()
self._state = 1
if self._state == 1:
try:
suspend_val = next(self._bar_iter)
# propagate the suspended value to the caller
# don't change _state, we will return here for
# as long as bar() keeps suspending
return suspend_val
except StopIteration as stop:
# we got our value
y = stop.value
# since we got the value, immediately proceed to
# invoking `baz`
baz(self._x, y)
self._state = 2
# tell the caller that we're done and inform
# it of the return value
raise StopIteration(42)
# the final state only serves to disable accidental
# resumption of a finished coroutine
raise RuntimeError("cannot reuse already awaited coroutine")
我们可以使用真正的 asyncio 测试我们的“协程”是否工作:
>>> class coro:
... (definition from above)
...
>>> def foo():
... print('foo')
... return 20
...
>>> async def bar():
... print('bar')
... return 10
...
>>> def baz(x, y):
... print(x, y)
...
>>> asyncio.run(coro())
foo
bar
20 10
42
剩下的部分就是用Python/C或者pybind11编写coro
类
关于python - 有没有办法从 C++ 调用 `async` python 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54553907/
我想了解 Ruby 方法 methods() 是如何工作的。 我尝试使用“ruby 方法”在 Google 上搜索,但这不是我需要的。 我也看过 ruby-doc.org,但我没有找到这种方法。
Test 方法 对指定的字符串执行一个正则表达式搜索,并返回一个 Boolean 值指示是否找到匹配的模式。 object.Test(string) 参数 object 必选项。总是一个
Replace 方法 替换在正则表达式查找中找到的文本。 object.Replace(string1, string2) 参数 object 必选项。总是一个 RegExp 对象的名称。
Raise 方法 生成运行时错误 object.Raise(number, source, description, helpfile, helpcontext) 参数 object 应为
Execute 方法 对指定的字符串执行正则表达式搜索。 object.Execute(string) 参数 object 必选项。总是一个 RegExp 对象的名称。 string
Clear 方法 清除 Err 对象的所有属性设置。 object.Clear object 应为 Err 对象的名称。 说明 在错误处理后,使用 Clear 显式地清除 Err 对象。此
CopyFile 方法 将一个或多个文件从某位置复制到另一位置。 object.CopyFile source, destination[, overwrite] 参数 object 必选
Copy 方法 将指定的文件或文件夹从某位置复制到另一位置。 object.Copy destination[, overwrite] 参数 object 必选项。应为 File 或 F
Close 方法 关闭打开的 TextStream 文件。 object.Close object 应为 TextStream 对象的名称。 说明 下面例子举例说明如何使用 Close 方
BuildPath 方法 向现有路径后添加名称。 object.BuildPath(path, name) 参数 object 必选项。应为 FileSystemObject 对象的名称
GetFolder 方法 返回与指定的路径中某文件夹相应的 Folder 对象。 object.GetFolder(folderspec) 参数 object 必选项。应为 FileSy
GetFileName 方法 返回指定路径(不是指定驱动器路径部分)的最后一个文件或文件夹。 object.GetFileName(pathspec) 参数 object 必选项。应为
GetFile 方法 返回与指定路径中某文件相应的 File 对象。 object.GetFile(filespec) 参数 object 必选项。应为 FileSystemObject
GetExtensionName 方法 返回字符串,该字符串包含路径最后一个组成部分的扩展名。 object.GetExtensionName(path) 参数 object 必选项。应
GetDriveName 方法 返回包含指定路径中驱动器名的字符串。 object.GetDriveName(path) 参数 object 必选项。应为 FileSystemObjec
GetDrive 方法 返回与指定的路径中驱动器相对应的 Drive 对象。 object.GetDrive drivespec 参数 object 必选项。应为 FileSystemO
GetBaseName 方法 返回字符串,其中包含文件的基本名 (不带扩展名), 或者提供的路径说明中的文件夹。 object.GetBaseName(path) 参数 object 必
GetAbsolutePathName 方法 从提供的指定路径中返回完整且含义明确的路径。 object.GetAbsolutePathName(pathspec) 参数 object
FolderExists 方法 如果指定的文件夹存在,则返回 True;否则返回 False。 object.FolderExists(folderspec) 参数 object 必选项
FileExists 方法 如果指定的文件存在返回 True;否则返回 False。 object.FileExists(filespec) 参数 object 必选项。应为 FileS
我是一名优秀的程序员,十分优秀!