Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么asyncio.Future与concurrent.futures.Future不兼容?_Python_Python 3.x_Concurrency_Python Asyncio_Concurrent.futures - Fatal编程技术网

Python 为什么asyncio.Future与concurrent.futures.Future不兼容?

Python 为什么asyncio.Future与concurrent.futures.Future不兼容?,python,python-3.x,concurrency,python-asyncio,concurrent.futures,Python,Python 3.x,Concurrency,Python Asyncio,Concurrent.futures,这两个类代表了并发编程的优秀抽象,因此它们不支持相同的API有点令人不安 具体地说,根据: asyncio.Future几乎与concurrent.futures.Future兼容 差异: result()和exception()在未来尚未完成时,不要接受超时参数并引发异常 使用add\u done\u callback()注册的回调始终通过事件循环的call\u soon\u threadsafe()调用 此类与concurrent.futures包中的wait()和as_completed

这两个类代表了并发编程的优秀抽象,因此它们不支持相同的API有点令人不安

具体地说,根据:

asyncio.Future
几乎与
concurrent.futures.Future
兼容

差异:

  • result()
    exception()
    在未来尚未完成时,不要接受超时参数并引发异常
  • 使用
    add\u done\u callback()
    注册的回调始终通过事件循环的
    call\u soon\u threadsafe()
    调用
  • 此类与
    concurrent.futures
    包中的
    wait()
    as_completed()
    函数不兼容
上面的列表实际上不完整,还有几个不同之处:

  • running()
    方法不存在
  • result()
    exception()
    如果调用得太早,可能会引发
    InvalidStateError
这些都是由于事件循环的固有性质导致的吗?它使这些操作要么无用,要么太麻烦而无法实现


add\u done\u callback()
相关的差异有什么意义?无论哪种方式,回调都保证在未来完成后的某个未指定的时间发生,因此这两个类之间不是完全一致吗?

并发。未来提供了一种在不同线程和进程之间共享结果的方法,通常在使用时

asyncio.Future
解决了相同的任务,但实际上是一些特殊类型的函数,通常在一个进程/线程中异步运行。当前上下文中的“异步”意味着事件循环管理此协程的代码执行流:它可以在一个协程内暂停执行,开始执行另一个协程,然后返回到执行第一个协程-通常在一个线程/进程中的所有内容

这些对象(以及许多其他/对象,如
Lock
Event
信号灯
等)看起来很相似,因为代码中线程/进程和协同程序的并发性思想是相似的

我认为对象不同的主要原因是历史:
asyncio
创建得比
threading
concurrent.futures
晚得多。在不破坏类API的情况下,将
concurrent.futures.Future
更改为使用
asyncio
可能是不可能的

在“理想世界”中,两个阶级应该是一个吗?这可能是一个有争议的问题,但我看到了它的许多缺点:虽然
asyncio
threading
乍看起来很相似,但它们在很多方面都非常不同,包括内部实现或编写异步/非异步代码的方式(请参见
async
/
wait
关键字)


我认为类的不同可能是最好的:我们显然在本质上划分了不同的并发方式(即使它们的相似性一开始看起来很奇怪)。

差异的核心原因在于线程(和进程)处理块的方式与协程处理阻塞事件的方式。在线程化中,当前线程将被挂起,直到任何条件解决并且线程可以继续。例如,在期货的情况下,如果您请求期货的结果,则可以暂停当前线程,直到该结果可用

然而,事件循环的并发模型是,您不挂起代码,而是返回到事件循环,并在准备就绪时再次被调用。因此,请求未准备好结果的asyncio未来的结果是错误的

您可能会认为asyncio的未来可能只是等待,虽然这将是低效的,但它真的会对您的协同程序造成如此严重的阻碍吗?事实证明,拥有协同程序块很可能意味着未来永远不会完成。未来的结果很可能由与运行请求结果的代码的事件循环相关联的一些代码设置。如果运行该事件循环的线程阻塞,则不会运行与该事件循环关联的代码。因此,阻塞结果将导致死锁并阻止生成结果

所以,是的,接口的差异是由于这种固有的差异。例如,您不希望将asyncio future与concurrent.futures抽象一起使用,因为这同样会阻塞事件循环线程

add\u done\u回调
差异保证回调将在事件循环中运行。这是可取的,因为它们将获得事件循环的线程本地数据。此外,许多协同程序代码都假定它永远不会与来自同一事件循环的其他代码同时运行。也就是说,在同一事件循环中的两个协程不同时运行的假设下,协程是线程安全的。在事件循环中运行回调可以避免许多线程安全问题,并使编写正确代码变得更容易