标签: python-asyncio

迭代asyncio.coroutine

我最近一直在使用asyncio,虽然我开始对它的工作原理有所了解,但我还是无法做到.我不确定是不是因为我的构造错误了,或者有什么理由说我为什么要做的事情没有意义.

简而言之,我希望能够迭代一个让步的asyncio.coroutine.例如,我希望能够做到这样的事情:

@asyncio.coroutine
def countdown(n):
    while n > 0:
        yield from asyncio.sleep(1)
        n = n - 1
        yield n

@asyncio.coroutine
def do_work():
    for n in countdown(5):
        print(n)

loop.run_until_complete(do_work())
Run Code Online (Sandbox Code Playgroud)

然而,这引起了asyncio的一个例外.我尝试了其他的东西,for n in (yield from countdown(5)): ...但是它也提供了类似的不透明的运行时异常.

我不能立即明白为什么你不应该做这样的事情,但是我已经达到理解正在发生的事情的极限.

所以:

  • 如果可以这样做,我该怎么办?
  • 如果不可能,为什么不呢?

如果这个问题不清楚,请告诉我!

python python-3.4 python-asyncio

8
推荐指数
1
解决办法
1906
查看次数

每个python进程的Asyncio事件循环(aioprocessing,多个事件循环)

我有两个过程; 主进程和子进程.主进程正在运行asyncio事件循环,并启动子进程.我想在子进程中启动另一个asyncio事件循环.我正在使用该 aioprocessing模块启动子进程.

子进程函数是:

def subprocess_code():
     loop = asyncio.get_event_loop()
     @asyncio.coroutine
     def f():
        for i in range(10):
            print(i)
            yield from asyncio.sleep(1)
     loop.run_until_complete(f())
Run Code Online (Sandbox Code Playgroud)

但是我收到一个错误:

    loop.run_until_complete(f())
  File "/usr/lib/python3.4/asyncio/base_events.py", line 271, in run_until_complete
    self.run_forever()
  File "/usr/lib/python3.4/asyncio/base_events.py", line 239, in run_forever
    raise RuntimeError('Event loop is running.')
RuntimeError: Event loop is running.
Run Code Online (Sandbox Code Playgroud)

是否可以asyncio在子进程中启动新的或重新启动现有的事件循环?如果是这样,怎么样?

python python-asyncio

8
推荐指数
1
解决办法
2657
查看次数

是否可以只运行asyncio事件循环的一个步骤

我正在使用asyncio和tkinter开发一个简单的图形网络应用程序.我遇到了将asyncio事件循环与Tk的mainloop相结合的问题.如果可能的话,我想在没有线程的情况下这样做,因为这两个库(但特别是tkinter)都不是非常线程安全的.目前,我在asyncio协程中使用Tk.update,它只运行tk事件循环的一次迭代:

@asyncio.coroutine
def run_tk(tk, interval=0.1):
    try:
        while True:
            tk.update()
            yield from asyncio.sleep(interval)
    except TclError as e:
        if "application has been destroyed" not in e.args[0]:
            raise
Run Code Online (Sandbox Code Playgroud)

但是,为了探索所有选项,我想知道是否可以执行反向 - 如果可以在tk回调中仅调用asyncio事件循环的单次迭代.

python events tk-toolkit tkinter python-asyncio

8
推荐指数
1
解决办法
1675
查看次数

python asyncio运行事件循环一次?

我试图了解asyncio库,特别是使用套接字.我写了一些代码以试图获得理解,

我想异步运行发送器和接收器套接字.我到了最后一个发送所有数据的地步,但是我必须再运行一个循环.看看如何做到这一点,我从stackoverflow找到了这个链接,我在下面实现了 - 但是这里发生了什么?是否有更好/更理智的方式来做到这一点,而不是打电话stop跟随run_forever?

stop()事件循环中的文档是:

停止运行事件循环.

调用stop()之前安排的每个回调都将运行.调用stop()后调度的回调将不会运行.但是,如果稍后再次调用run_forever(),那些回调将会运行.

而且run_forever()的文件是:

运行直到调用stop().

问题:

  • 为什么世界上run_forever唯一的出路run_once?这甚至没有意义
  • 有一个更好的方法吗?
  • 我的代码看起来像是使用asyncio库编程的合理方式吗?
  • 是否有更好的方法将事件添加到事件循环中asyncio.async()?loop.create_task在我的Linux系统上出错.

https://gist.github.com/cloudformdesign/b30e0860497f19bd6596

python sockets asyncsocket python-asyncio

8
推荐指数
1
解决办法
4126
查看次数

将作业提交到asyncio事件循环

我想将作业从一个线程提交到一个asyncio事件循环(就像run_in_executor,但反过来说).

以下是asyncio文档中有关并发和多线程的内容:

要从不同的线程安排回调,应使用BaseEventLoop.call_soon_threadsafe()方法.从不同的线程安排协程的示例: loop.call_soon_threadsafe(asyncio.async, coro_func())

这工作正常,但协程的结果丢失了.

相反,可以使用一个函数将完成的回调添加到async(或ensure_future)返回的未来,以便线程可以通过concurrent.futures.Future访问结果.

是否有特殊原因导致标准库中未实现此类功能?或者我错过了一种更简单的方法来实现这一目标?

python multithreading python-asyncio

8
推荐指数
1
解决办法
3857
查看次数

阻止jupyter笔记本单元执行直到收到特定消息

我正在尝试为python实现异步,分布式计算引擎,它与jupyter notebook兼容.该系统应该基于"推送通知"方法,这使得(几乎,我希望)不可能允许用户等待特定的计算结果(即,给定笔记本单元的块执行直到具有预期结果的消息被传递).确切地说,我试图:

  1. 将新任务添加到jupyter notebook事件循环(该任务定期检查特定msg是否已在循环中到达,当msg到达时中断)
  2. 阻止当前单元格等待任务完成.
  3. 仍然能够处理传入的消息(使用RabbitMQ,Pika,来自http://pika.readthedocs.io/en/0.10.0/examples/asynchronous_consumer_example.html的略微修改的代码)

我准备好了解决我的问题的笔记本:https://github.com/SLEEP-MAN/RabbitMQ_jupyterNotebook_asyncio

有任何想法吗?是否有可能(可能是一些IPython/IpyKernel魔法;>?),或者我必须将我的方法改为180度?

python rabbitmq pika python-asyncio jupyter-notebook

8
推荐指数
1
解决办法
589
查看次数

如何使用Ctrl-C优雅地终止asyncio脚本?

我已经阅读了所有可以找到的有关如何优雅地处理带有asyncio事件循环并以Ctrl-C终止的脚本的文章,而且在我不打印一个或多个回溯的情况下,我无法使其中的任何一个都能正常工作这样做。答案几乎无处不在,我还无法在这个小脚本中实现其中的任何一个:

import asyncio
import datetime
import functools
import signal


async def display_date(loop):
    end_time = loop.time() + 5.0
    while True:
        print(datetime.datetime.now())
        if (loop.time() + 1.0) >= end_time:
            break
        await asyncio.sleep(1)


def stopper(signame, loop):
    print("Got %s, stopping..." % signame)
    loop.stop()


loop = asyncio.get_event_loop()
for signame in ('SIGINT', 'SIGTERM'):
    loop.add_signal_handler(getattr(signal, signame), functools.partial(stopper, signame, loop))

loop.run_until_complete(display_date(loop))
loop.close()
Run Code Online (Sandbox Code Playgroud)

我想让脚本退出,而不在Ctrl-C(或通过发送的SIGTERM / SIGINT kill)之后打印任何回溯。这段代码RuntimeError: Event loop stopped before Future completed.以我根据先前的答案尝试过的许多其他形式打印,我得到了很多其他类型的异常类和错误消息,却不知道如何解决它们。上面的代码现在很小,但是我之前所做的一些尝试不过是什么,而且都不是正确的。

如果您能够修改脚本以使其优雅地终止,那么不胜感激地向您解释为什么这样做是正确的方法。

python signals sigint python-asyncio

8
推荐指数
2
解决办法
3732
查看次数

在协同链接期间,await如何将控制权交还给事件循环?

我正在尝试使用Python 3.6中的asyncio,并且很难弄清楚为什么这段代码的行为方式如此.

示例代码:

import asyncio

async def compute_sum(x, y):
    print("Compute %s + %s ..." % (x, y))
    await asyncio.sleep(5)
    print("Returning sum")
    return x + y

async def compute_product(x, y):
    print("Compute %s x %s ..." % (x, y))
    print("Returning product")
    return x * y

async def print_computation(x, y):
    result_sum = await compute_sum(x, y)
    result_product = await compute_product(x, y)
    print("%s + %s = %s" % (x, y, result_sum))
    print("%s * %s = %s" % (x, y, result_product))

loop = asyncio.get_event_loop()
loop.run_until_complete(print_computation(1, 2)) …
Run Code Online (Sandbox Code Playgroud)

python python-3.x async-await python-asyncio

8
推荐指数
1
解决办法
635
查看次数

同时观察子进程的stdout和stderr

如何同时查看长时间运行的子进程的标准输出和标准错误,在子进程生成后立即处理每一行?

我不介意使用Python3.6的异步工具来制作我希望在两个流中的每个流上的非阻塞异步循环,但这似乎无法解决问题.以下代码:

import asyncio
from asyncio.subprocess import PIPE
from datetime import datetime


async def run(cmd):
    p = await asyncio.create_subprocess_shell(cmd, stdout=PIPE, stderr=PIPE)
    async for f in p.stdout:
        print(datetime.now(), f.decode().strip())
    async for f in p.stderr:
        print(datetime.now(), "E:", f.decode().strip())

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(run('''
         echo "Out 1";
         sleep 1;
         echo "Err 1" >&2;
         sleep 1;
         echo "Out 2"
    '''))
    loop.close()
Run Code Online (Sandbox Code Playgroud)

输出:

2018-06-18 00:06:35.766948 Out 1
2018-06-18 00:06:37.770187 Out 2
2018-06-18 00:06:37.770882 E: Err 1
Run Code Online (Sandbox Code Playgroud)

虽然我希望它输出如下:

2018-06-18 00:06:35.766948 Out 1
2018-06-18 …
Run Code Online (Sandbox Code Playgroud)

python subprocess python-asyncio

8
推荐指数
2
解决办法
429
查看次数

aiohttp并发GET请求导致ClientConnectorError(8,'提供nodename或servname,或者未知')

我被一个似乎与asyncio+ 相关的问题困扰,aiohttp因此,当发送大量并发GET请求时,超过85%的请求引发了一个aiohttp.client_exceptions.ClientConnectorError异常,最终源于

socket.gaierror(8, 'nodename nor servname provided, or not known')
Run Code Online (Sandbox Code Playgroud)

在主机/端口上发送单个GET请求或执行基础DNS解析时,不会引发此异常.

虽然在我的真实代码中,我正在进行大量自定义,例如使用自定义TCPConnector实例,但我可以仅使用"默认" aiohttp类实例和参数来重现问题,如下所示.

我跟踪了回溯,异常的根与DNS解析有关.它来自于调用的_create_direct_connection方法.aiohttp.TCPConnector._resolve_host()

我也尝试过:

  • 使用(而不是使用) aiodns
  • sudo killall -HUP mDNSResponder
  • 使用family=socket.AF_INET作为参数TCPConnector(虽然我很确定aiodns无论如何都使用它).这使用2而不是默认的int 0到该参数
  • 随着ssl=True和ssl=False

一切都无济于事.


完整的代码重现如下.输入的URL位于https://gist.github.com/bsolomon1124/fc625b624dd26ad9b5c39ccb9e230f5a.

import asyncio
import itertools

import aiohttp
import aiohttp.client_exceptions

from yarl import URL

ua = itertools.cycle(
    (
        "Mozilla/5.0 (X11; Linux i686; rv:64.0) Gecko/20100101 Firefox/64.0",
        "Mozilla/5.0 (Macintosh; U; Intel …
Run Code Online (Sandbox Code Playgroud)

python python-3.x python-asyncio aiohttp

8
推荐指数
1
解决办法
400
查看次数