想象一下以下非常常见的情况:您已经编写了一个长而复杂的函数,并且意识到一些代码应该被提取到一个单独的函数中,以便重用和/或可读性.通常,这个额外的函数调用不会改变程序的语义.

然而,现在假设您的函数是一个协程,并且您想要提取的代码至少包含一个异步调用.现在,通过插入一个新的点,将其提取到一个单独的函数中,突然改变了程序的语义.在这个点上,协程产生,事件循环获得控制,任何其他协程都可以在其间进行调度.

之前的例子:

async def complicated_func():
    foo()
    bar()
    await baz()

例如:

async def complicated_func():
    foo()
    await extracted_func()

async def extracted_func():
    bar()
    await baz()

在前面的示例中,保证complicated_func不会在呼叫foo()和呼叫bar()之间被挂起.重构后,这种保证就失go 了.

我的问题是:是否可以调用extracted_func(),使其立即执行,就好像其代码是内联的?或者有没有其他方法可以在不改变程序语义的情况下执行这种常见的重构任务?

推荐答案

重构后,这种保证就失go 了.

其实不是.

是否可以调用extracted_func(),使其立即执行,就像其代码是内联的一样?

事实已经如此.

await some_coroutine()意味着some_coroutine可能会将控制权交还给事件循环,但它不会这样做,直到它真正等待future (例如某些I/O操作).

考虑这个例子:

import asyncio

async def coro():
    print(1)
    await asyncio.sleep(0)
    print(3)

async def main():
    loop.call_soon(print, 2)
    await coro()

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

请注意,2是如何在13之间按预期打印的.

这也意味着可以通过编写以下代码来冻结事件循环:

async def coro():
    return

async def main():
    while True:
        await coro()

在这种情况下,事件循环永远没有机会运行另一个任务.

Python-3.x相关问答推荐

如何强调您正在寻求以 pandas 数据帧的另一列为条件的差异?

Django 模型类方法使用错误的 `self`

使用Python按照其组/ID的紧密值的递增顺序映射数据框的两列

使用 NaN 计算 pct_change 时如何避免 bfill 或 ffill

在 pytest 中,如何测试 sys.exit('some error message')?

将 pandas Timestamp() 转换为 datetime.datetime() 以支持 peewee DateTimeField()

Python.在循环中填充字典的问题

BeautifulSoup 和 pd.read_html - 如何将链接保存到最终数据框中的单独列中?

smtplib 在 Python 3.1 中发送带有 unicode 字符的邮件的问题

简单的 get/post 请求在 python 3 中被阻止,但在 python 2 中没有

如何使我的课程在 Python 中非常可打印?

使用 distutils 分发预编译的 python 扩展模块

如何判断一个字符串是否包含有效的 Python 代码

为什么 2to3 将 mydict.keys() 更改为 list(mydict.keys())?

try 在 Windows 10 高 DPI 显示器上解决模糊的 tkinter 文本 + zoom ,但担心我的方法不是 Pythonic 或不安全

从 csv 中删除单行而不复制文件

如何对字典的函数输出列表进行单元测试?

python asyncio add_done_callback 与 async def

在动态链接库 Anaconda3\Library\bin\mkl_intel_thread.dll 中找不到序数 242

如何在 Python 3.4 中使用 pip 3?