标签: python-asyncio

Python异步AttributeError aexit

我AttributeError: __aexit__在下面的代码中不断出错,但我真的不明白为什么会发生这种情况。

我的 Python 版本是: 3.6.4 (v3.6.4:d48eceb, Dec 19 2017, 06:04:45) [MSC v.1900 32 bit (Intel)]

import aiohttp
import asyncio
import tqdm


async def fetch_url(session_, url_, timeout_=10):
    with aiohttp.Timeout(timeout_):
        async with session_.get(url_) as response:
            text = await response.text()
            print("URL: {} - TEXT: {}".format(url_, len(text)))
            return text


async def parse_url(session, url, timeout=10):
    # get doc from url
    async with await fetch_url(session, url, timeout) as doc:
        print("DOC: {}".format(doc, len(doc)))
        return doc


async def parse_urls(session, urls, loop):
    tasks = [parse_url(session, url) …
Run Code Online (Sandbox Code Playgroud)

python-3.x async-await python-asyncio

13
推荐指数
1
解决办法
2万
查看次数

RuntimeError:超时上下文管理器应该在任务中使用

背景:我在 Discord 客户端旁边托管了一个 Flask 服务器

Flask 服务器只需要将来自客户端的消息传递给 discord,并将来自 discord 的消息传递给客户端。

我得到的错误,当我打电话loop.run_until_complete(sendMsg(request)) 我试图wait_for在sendMsg和wait_for loop.run_until_complete()

我到处找,没有找到任何东西,所以任何帮助将不胜感激。

代码:

import discord
import json
import os
import asyncio
from flask import Flask, request, render_template
from async_timeout import timeout
from threading import Thread
from time import sleep

client = discord.Client()
messages = []
app = Flask(__name__)

def startClient():
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    client.run('token')


#
# Discord Events
#
@client.event
async def on_ready():
    print('Discord Client Ready')

@client.event
async def on_message(message):
    global …
Run Code Online (Sandbox Code Playgroud)

python flask python-asyncio discord.py

13
推荐指数
4
解决办法
2万
查看次数

运行两个异步函数而不互相阻塞

我有一个异步函数,我想“并行”运行另一个异步函数。但我需要在第一个函数内的某个时刻执行此操作。

我见过很多例子,但它们都同时启动两个功能,这不是我想要的。

我创建了这个简单的示例来说明我想要实现的目标(以及我尝试过的目标):

import asyncio
import time

async def print_letters():
    for letter in ['A', 'B', 'C', 'D']:
        print(letter)
        time.sleep(1)

async def print_numbers(loop):
    for number in range(1, 7):
        if(number == 3):
            # same result with create_task
            # loop.create_task(print_letters())
            asyncio.ensure_future(print_letters())
        print(number)
        time.sleep(1)

loop = asyncio.get_event_loop()
loop.run_until_complete(print_numbers(loop))
print('End')
Run Code Online (Sandbox Code Playgroud)

电流输出:

1、2、3、4、5、6、A、B、C、D、结束

所需的输出将是这样的:

1、2、3、A、4、B、5、C、6 D、结束

我尝试过其他一些东西(asyncio.wait例如),但没有一个按预期工作。另外,当您刚接触 Python 时,文档也不容易理解asyncio。

如果问题不清楚或缺少某些内容,请告诉我,以便我进行编辑。我很感激任何形式的帮助。

Python 3.6.2

python asynchronous python-3.x python-asyncio

13
推荐指数
1
解决办法
2万
查看次数

在异步生成器上使用 next()

next()可以使用内置函数逐步迭代生成器。例如:

def sync_gen(n):
    """Simple generator"""
    for i in range(n):
        yield i**2

sg = sync_gen(4)
print(next(sg)) # -> 0
print(next(sg)) # -> 1
print(next(sg)) # -> 4
Run Code Online (Sandbox Code Playgroud)

在异步生成器上使用next()不起作用:

import asyncio

async def async_gen(n):
    for i in range(n):
        yield i**2

async def main():
    print("Async for:")
    async for v in async_gen(4):  # works as expected
        print(v)

    print("Async next:")
    ag = async_gen(4)
    v = await next(ag) # raises: TypeError: 'async_generator' object is not an iterator
    print(v)

asyncio.run(main())
Run Code Online (Sandbox Code Playgroud)

是否存在类似的东西v = await …

python python-3.x python-asyncio

13
推荐指数
2
解决办法
1万
查看次数

使用 Motor AsyncIO 和 Pytest 测试 MongoDB 功能

所以我正在尝试编写几个测试来测试我使用异步 MongoDB 连接的函数。为了连接到 MongoDB,我使用 Motor 和 asyncio。我需要帮助模拟电机连接。

我的代码:

公地.py

mongo = None
Run Code Online (Sandbox Code Playgroud)

黑名单.py

import commons

class Blacklist(object):
    async def check_if_blacklisted(self, word: str):
        blacklisted = False
        if await commons.mongo.dbtest.blacklist.find_one({'word': word}):
            blacklisted = True
        return blacklisted
Run Code Online (Sandbox Code Playgroud)

主文件

import asyncio
from blacklist import Blacklist
from motor.motor_asyncio import AsyncIOMotorClient
import commons

async def run():
    commons.mongo = AsyncIOMotorClient("mongodb://localhost", io_loop=asyncio.get_event_loop())
    blacklist_checker = Blacklist()
    result = await blacklist_checker.check_if_blacklisted(word="should_be_false")
    print(result)
    # > False

    result = await blacklist_checker.check_if_blacklisted(word="should_be_true")
    print(result)
    # > True

loop = asyncio.get_event_loop()
loop.run_until_complete(run())
loop.close()
Run Code Online (Sandbox Code Playgroud)

我现在想通过模拟电机连接来测试 blacklist.py,但我似乎无法正常运行测试。以下是我尝试过的代码: …

python mocking mongodb pytest python-asyncio

13
推荐指数
1
解决办法
1136
查看次数

异步上下文管理器是否需要保护它们的清理代码不被取消?

问题(我认为)

该contextlib.asynccontextmanager文档给出了这样的例子:

@asynccontextmanager
async def get_connection():
    conn = await acquire_db_connection()
    try:
        yield conn
    finally:
        await release_db_connection(conn)
Run Code Online (Sandbox Code Playgroud)

在我看来,这可能会泄漏资源。如果此代码的任务在此代码在其行上时被取消await release_db_connection(conn),则发布可能会中断。在asyncio.CancelledError将从某处内向上传播finally块,从而防止随后的清理代码运行。

因此,实际上,如果您正在实现一个处理超时请求的 Web 服务器,则在完全错误的时间触发超时可能会导致数据库连接泄漏。

完整的可运行示例

import asyncio
from contextlib import asynccontextmanager

async def acquire_db_connection():
    await asyncio.sleep(1)
    print("Acquired database connection.")
    return "<fake connection object>"

async def release_db_connection(conn):
    await asyncio.sleep(1)
    print("Released database connection.")

@asynccontextmanager
async def get_connection():
    conn = await acquire_db_connection()
    try:
        yield conn
    finally:
        await release_db_connection(conn)

async def do_stuff_with_connection():
    async with get_connection() as conn:
        await …
Run Code Online (Sandbox Code Playgroud)

python resource-cleanup resource-leak cancellation python-asyncio

13
推荐指数
1
解决办法
231
查看次数

Python的asyncio,期货和收益率

考虑以下程序(在CPython 3.4.0b1上运行):

import math
import asyncio
from asyncio import coroutine

@coroutine
def fast_sqrt(x):
   future = asyncio.Future()
   if x >= 0:
      future.set_result(math.sqrt(x))
   else:
      future.set_exception(Exception("negative number"))
   return future


def slow_sqrt(x):
   yield from asyncio.sleep(1)
   future = asyncio.Future()
   if x >= 0:
      future.set_result(math.sqrt(x))
   else:
      future.set_exception(Exception("negative number"))
   return future


@coroutine
def run_test():
   for x in [2, -2]:
      for f in [fast_sqrt, slow_sqrt]:
         try:
            future = yield from f(x)
            print("\n{} {}".format(future, type(future)))
            res = future.result()
            print("{} result: {}".format(f, res))
         except Exception as e:
            print("{} exception: {}".format(f, …
Run Code Online (Sandbox Code Playgroud)

python yield future coroutine python-asyncio

12
推荐指数
1
解决办法
1万
查看次数

在asyncio.Protocol.data_received中调用协同程序

我asyncio.Protocol.data_received在新的Python asyncio模块的回调中执行异步操作时遇到问题.

考虑以下服务器:

class MathServer(asyncio.Protocol):

   @asyncio.coroutine
   def slow_sqrt(self, x):
      yield from asyncio.sleep(1)
      return math.sqrt(x)

   def fast_sqrt(self, x):
      return math.sqrt(x)

   def connection_made(self, transport):
      self.transport = transport

   #@asyncio.coroutine
   def data_received(self, data):
      print('data received: {}'.format(data.decode()))
      x = json.loads(data.decode())
      #res = self.fast_sqrt(x)
      res = yield from self.slow_sqrt(x)
      self.transport.write(json.dumps(res).encode('utf8'))
      self.transport.close()
Run Code Online (Sandbox Code Playgroud)

与以下客户一起使用:

class MathClient(asyncio.Protocol):

   def connection_made(self, transport):
      transport.write(json.dumps(2.).encode('utf8'))

   def data_received(self, data):
      print('data received: {}'.format(data.decode()))

   def connection_lost(self, exc):
      asyncio.get_event_loop().stop()
Run Code Online (Sandbox Code Playgroud)

随着self.fast_sqrt被召唤,一切都按预期工作.

有self.slow_sqrt,它不起作用.

它也不适用self.fast_sqrt于@asyncio.coroutine装饰器data_received.

我觉得我在这里缺少一些基本的东西.

完整的代码在这里: …

python network-programming yield coroutine python-asyncio

12
推荐指数
1
解决办法
3587
查看次数

为什么我不能在asyncio事件循环运行时捕获SIGINT?

在Windows上使用Python 3.4.1,我发现在执行asyncio事件循环时,我的程序不能被中断(即在终端中按Ctrl + C).更重要的是,SIGINT信号被忽略.相反,我已经确定在不在事件循环中时处理SIGINT.

为什么执行asyncio事件循环时会忽略SIGINT?

下面的程序应该演示问题 - 在终端中运行它并尝试通过按Ctrl + C来停止它,它应该继续运行:

import asyncio
import signal


# Never gets called after entering event loop
def handler(*args):
    print('Signaled')


signal.signal(signal.SIGINT, handler)

print('Event loop starting')
loop = asyncio.SelectorEventLoop()
asyncio.set_event_loop(loop)
loop.run_forever()
print('Event loop ended')
Run Code Online (Sandbox Code Playgroud)

请参阅官方(郁金香)邮件列表上的讨论.

windows signals event-loop python-3.4 python-asyncio

12
推荐指数
2
解决办法
3547
查看次数

python asyncio add_done_callback with async def

我有两个函数:第一个def_a是异步函数,第二个是def_b常规函数,调用结果def_a作为add_done_callback函数的回调函数.

我的代码看起来像这样:

import asyncio

def def_b(result):
    next_number = result.result()
    # some work on the next_number
    print(next_number + 1)

async def def_a(number):
    await some_async_work(number)
    return number + 1

loop = asyncio.get_event_loop()
task = asyncio.ensure_future(def_a(1))
task.add_done_callback(def_b)
response = loop.run_until_complete(task)
loop.close()
Run Code Online (Sandbox Code Playgroud)

它的工作非常完美.

当第二个函数def_b变为异步时,问题就开始了.现在它看起来像这样:

async def def_b(result):
    next_number = result.result()
    # some asynchronous work on the next_number
    print(next_number + 1)
Run Code Online (Sandbox Code Playgroud)

但是现在我无法将它提供给add_done_callback函数,因为它不是常规函数.

我的问题是 - 它是否可能,如果是异步的,我怎么能提供def_b给add_done_callback函数def_b?

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

12
推荐指数
2
解决办法
8053
查看次数