标签: python-asyncio

在asyncio协议/服务器之间进行通信

我正在尝试编写一个服务器端事件服务器,我可以使用telnet连接它,并将telnet内容推送到浏览器.使用Python和asyncio背后的想法是使用尽可能少的CPU,因为它将在Raspberry Pi上运行.

到目前为止,我有以下使用库中的库:https://pypi.python.org/pypi/asyncio-sse/0.1,它使用asyncio.

我还复制了一个使用asyncio的telnet服务器.

两者都分开工作,但我不知道如何将两者结合在一起.据我了解,我需要调用send()在SSEHandler从内部类Telnet.data_received,但我不知道如何访问它.这两个"服务器"都需要在循环中运行才能接受新连接或推送数据.

任何人都可以帮忙,或指向另一个方向?

import asyncio
import sse

# Get an instance of the asyncio event loop
loop = asyncio.get_event_loop()

# Setup SSE address and port
sse_host, sse_port = '192.168.2.25', 8888

class Telnet(asyncio.Protocol):
    def connection_made(self, transport):
        print("Connection received!");
        self.transport = transport

    def data_received(self, data):
        print(data)
        self.transport.write(b'echo:')
        self.transport.write(data)

        # This is where I want to send data via SSE
        # SSEHandler.send(data)

        # Things I've tried :(
        #loop.call_soon_threadsafe(SSEHandler.handle_request());
        #loop.call_soon_threadsafe(sse_server.send("PAH!"));

    def connection_lost(self, esc): …
Run Code Online (Sandbox Code Playgroud)

python python-asyncio

3
推荐指数
1
解决办法
1700
查看次数

asyncio中的信号量/多个池锁用于1个代理 - aiohttp

我有5,00,000个网址.并希望异步获得每个响应.

import aiohttp
import asyncio    

@asyncio.coroutine
def worker(url):
    response = yield from aiohttp.request('GET', url, connector=aiohttp.TCPConnector(share_cookies=True, verify_ssl=False))
    body = yield from response.read_and_close()

    print(url)

def main():
    url_list = [] # lacs of urls, extracting from a file

    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait([worker(u) for u in url_list]))

main()
Run Code Online (Sandbox Code Playgroud)

我一次想要200个连接(并发200个),而不是因为这个

当我运行这个程序50个网址它工作正常,url_list[:50] 但但如果我通过整个列表,我得到这个错误

aiohttp.errors.ClientOSError: Cannot connect to host www.example.com:443 ssl:True Future/Task exception was never retrieved future: Task()
Run Code Online (Sandbox Code Playgroud)

可能是频率太高,服务器拒绝在限制后做出响应?

python python-3.x python-asyncio aiohttp

3
推荐指数
1
解决办法
1319
查看次数

Python的asyncio同步工作

我正在尝试利用Python的新asyncio库来发送异步HTTP请求.我想timeout在发送每个请求之前等待几毫秒(变量) - 当然 - 异步发送它们,而不是在每个请求发送后等待响应.

我正在做类似以下的事情:

@asyncio.coroutine
def handle_line(self, line, destination):
    print("Inside! line {} destination {}".format(line, destination))
    response = yield from aiohttp.request('POST', destination, data=line,
                               headers=tester.headers)
    print(response.status)
    return (yield from response.read())

@asyncio.coroutine
def send_data(self, filename, timeout):
    destination='foo'
    logging.log(logging.DEBUG, 'sending_data')
    with open(filename) as log_file:
        for line in log_file:
            try:
                json_event = json.loads(line)
            except ValueError as e:
                print("Error parsing json event")
            time.sleep(timeout)
            yield from asyncio.async(self.handle_line(json.dumps(json_event), destination))


loop=asyncio.get_event_loop().run_until_complete(send_data('foo.txt', 1))
Run Code Online (Sandbox Code Playgroud)

我得到的输出(通过打印200个响应)看起来这个代码是同步运行的.我究竟做错了什么?

python asynchronous python-3.x python-asyncio

3
推荐指数
1
解决办法
1867
查看次数

这种使用线程池与龙卷风的风格好吗?

所以我在我的类中创建了一个名为executor的类变量

executor = ThreadPoolExecutor(100)
Run Code Online (Sandbox Code Playgroud)

而不是拥有函数和方法并使用装饰器,我只是使用以下行来处理我的异步方法中的阻塞任务(如io和哈希创建和......)

result = await to_tornado_future(self.executor.submit(blocking_method, param1, param2)
Run Code Online (Sandbox Code Playgroud)

我决定使用这种风格的原因

1-装饰者性质较慢

2-不需要额外的方法和功能

3-它按预期工作,并在需要之前不创建线程

我对吗 ?请使用原因(我想知道我使用的方式,更慢或使用更多资源或......)

更新

基于Ben回答,我的上述方法不正确所以我最终根据需要使用了以下功能,我认为这是最好的方法

def pool(pool_executor, fn, *args, **kwargs):
    new_future = Future()
    result_future = pool_executor.submit(fn, *args, **kwargs)
    result_future.add_done_callback(lambda f: new_future.set_result(f.result()))
    return new_future
Run Code Online (Sandbox Code Playgroud)

用法:

result = await pool(self.executor, time.sleep, 3)
Run Code Online (Sandbox Code Playgroud)

python multithreading tornado python-3.x python-asyncio

3
推荐指数
1
解决办法
693
查看次数

Python 2.7中有什么类似于Go的`time.Tick`或Netty的`HashedWheelTimer`?

我写了很多依赖于精确的周期性方法调用的代码.我一直在使用Python的futures库将调用提交到运行时的线程池,并在循环中的调用之间休眠:

executor = ThreadPoolExecutor(max_workers=cpu_count())

def remote_call():
    # make a synchronous bunch of HTTP requests

def loop():
    while True:
        # do work here
        executor.submit(remote_call)
        time.sleep(60*5)
Run Code Online (Sandbox Code Playgroud)

但是,我注意到这个实现在长时间运行后引入了一些漂移(例如,我运行此代码大约10个小时,并注意到大约7秒的漂移).对于我的工作,我需要在确切的秒上运行,毫秒甚至更好.有些人指出我asyncio("火与忘记"python async/await),但我无法在Python 2.7中使用它.

我不是在寻找黑客.我真正想要的是类似于Go time.Tick或Netty的东西HashedWheelTimer.

python go python-2.7 python-asyncio concurrent.futures

3
推荐指数
1
解决办法
178
查看次数

在Python中为非异步函数使用asyncio吗?

假设有一个可以进行各种数据库查询的库:

import time

def queryFoo():
    time.sleep(4)
    return "foo"

def queryBar():
    time.sleep(4)
    return "bar"
Run Code Online (Sandbox Code Playgroud)

我想同时执行这两个查询,而不必添加async到方法签名或添加装饰器。这些功能完全不应该依赖于异步。

在其中利用这些非异步功能的最佳方法是什么asyncio?

我正在寻找某种形式的东西:

#I need an 'asyncWrapper'

results = asyncio.gather(asyncWrapper(queryFoo()), asyncWrapper(queryBar()))
Run Code Online (Sandbox Code Playgroud)

预先感谢您的考虑和回应。

python python-3.x python-asyncio

3
推荐指数
2
解决办法
1735
查看次数

多个异步上下文管理器

是否可以在python中组合异步上下文管理器?类似于asyncio.gather,但能够与上下文管理器一起使用的东西.像这样的东西:

async def foo():
    async with asyncio.gather_cm(start_vm(), start_vm()) as vm1, vm2:
        await vm1.do_something()
        await vm2.do_something()
Run Code Online (Sandbox Code Playgroud)

这目前可能吗?

python python-asyncio

3
推荐指数
1
解决办法
301
查看次数

asyncio:从执行程序中的异步函数收集结果

一旦所有HTTP请求返回,我想启动大量HTTP请求并收集其结果。使用可以以非阻塞方式发送请求asyncio,但是我在收集其结果时遇到问题。

我知道针对此特定问题而设计的解决方案,例如aiohttp。但是HTTP请求只是一个例子,我的问题是如何asyncio正确使用。

在服务器端,我有flask可以localhost/用“ Hello World!” 回答每个请求,但是要等待0.1秒再回答。在所有示例中,我正在发送10个请求。同步代码大约需要1秒钟,异步版本则可以在0.1秒内完成。

在客户端,我想同时启动许多请求并收集其结果。我正在尝试以三种不同的方式来做到这一点。由于asyncio需要执行者来解决阻塞代码,因此所有方法都调用loop.run_in_executor。

这些代码在它们之间共享:

import requests
from time import perf_counter
import asyncio

loop = asyncio.get_event_loop()

async def request_async():
    r = requests.get("http://127.0.0.1:5000/")
    return r.text

def request_sync():
    r = requests.get("http://127.0.0.1:5000/")
    return r.text
Run Code Online (Sandbox Code Playgroud)

方法1:

asyncio.gather()在任务列表中使用,然后单击run_until_complete。阅读Asyncio.gather与asyncio.wait之后,似乎collect会等待结果。但事实并非如此。因此,此代码立即返回,而无需等待请求完成。如果我在此处使用阻止功能,则可以正常工作。为什么我不能使用异步功能?

# approach 1
start = perf_counter()
tasks = []
for i in range(10):
    tasks.append(loop.run_in_executor(None, request_async)) # <---- using async function !

gathered_tasks = asyncio.gather(*tasks)
results = loop.run_until_complete(gathered_tasks) …
Run Code Online (Sandbox Code Playgroud)

python asynchronous coroutine async-await python-asyncio

3
推荐指数
1
解决办法
3841
查看次数

在Python中加入多个异步生成器

我想侦听来自同一对象的多个实例的事件,然后将此事件流合并为一个流。例如,如果我使用异步生成器:

class PeriodicYielder: 
    def __init__(self, period: int) -> None: 
        self.period = period 

    async def updates(self): 
        while True: 
            await asyncio.sleep(self.period)
            yield self.period
Run Code Online (Sandbox Code Playgroud)

我可以成功监听一个实例的事件:

async def get_updates_from_one(): 
    each_1 = PeriodicYielder(1) 
    async for n in each_1.updates(): 
        print(n)
# 1
# 1
# 1
# ...
Run Code Online (Sandbox Code Playgroud)

但是,如何从多个异步生成器获取事件?换句话说:如何按多个异步生成器准备好产生下一个值的顺序进行迭代?

async def get_updates_from_multiple(): 
    each_1 = PeriodicYielder(1) 
    each_2 = PeriodicYielder(2) 
    async for n in magic_async_join_function(each_1.updates(), each_2.updates()): 
        print(n)
# 1
# 1
# 2
# 1
# 1
# 2
# ...
Run Code Online (Sandbox Code Playgroud)

stdlib或3rd party模块中是否有这种magic_async_join_function?

python python-asyncio

3
推荐指数
2
解决办法
524
查看次数

Python 3.7-asyncio.sleep()和time.sleep()

当我转到asyncio页面时,第一个示例是hello world程序。当我在python上运行它时3.73,我看不出与正常的任何区别,有人可以告诉我区别并举一个简单的例子吗?

In [1]: import asyncio
   ...:
   ...: async def main():
   ...:     print('Hello ...')
   ...:     await asyncio.sleep(5)
   ...:     print('... World!')
   ...:
   ...: # Python 3.7+
   ...: asyncio.run(main())
Hello ...
... World!

In [2]:

In [2]: import time
   ...:
   ...: def main():
   ...:     print('Hello ...')
   ...:     time.sleep(5)
   ...:     print('... World!')
   ...:
   ...: # Python 3.7+
   ...: main()
Hello ...
... World!
Run Code Online (Sandbox Code Playgroud)

我故意将时间从1秒增加到5秒,希望看到一些特别的东西,但我没有。

python python-3.x python-asyncio python-3.7

3
推荐指数
2
解决办法
2377
查看次数