0

I am having an issue with python 3.8.5 vs 3.7

given method:

import asyncio
import functools

_executor = ThreadPoolExecutor()


async def request_async(*args, **kwargs) -> requests.Response:
    loop = asyncio.get_event_loop()
    response = await loop.run_in_executor(_executor, functools.partial(requests.request, *args, **kwargs))
    return response

and a call:

 response = await request_async(protocol, url, headers=headers, *args, **kwargs)

^^ works in python 3.7 and returns a Response as per signature although in python 3.8 returns a Future in order to get to work needs to be awaited second time.

 response = await (await request_async(protocol, url, headers=headers, *args, **kwargs))

I would appreciate some insights where to look and why it would happen.

snakecharmerb
  • 47,570
  • 11
  • 100
  • 153
Matt
  • 1
  • 2
    Hi there, I am attempting to reproduce your issue, but I'm having a little bit of trouble, as the example code you have given does not execute. It needs `from concurrent.futures import ThreadPoolExecutor` I presume, but your `request_async` also references `requests` and I've been unable to figure out what that's supposed to be. Can you edit your code to correct it? – OmnipotentEntity Jul 29 '21 at 18:14
  • +1 To @OmnipotentEntity - eg.: arent you using aiohttp request which is awaitable? BTW. Why are you not using aiohttp request directly? – Petr Synek Jul 29 '21 at 19:30

1 Answers1

0

This code produces the same output in both python 3.8.5 and python 3.7.8:

import asyncio
import functools
import requests
from concurrent.futures import ThreadPoolExecutor 

_executor = ThreadPoolExecutor()

async def request_async(*args, **kwargs) -> requests.Response:
  loop = asyncio.get_event_loop()
  response = await loop.run_in_executor(_executor, functools.partial(requests.request, *args, **kwargs))
  return response

loop = asyncio.get_event_loop()
req_result = loop.run_until_complete(request_async('GET', "http://example.com/"))
loop.close()

print(req_result)

Note that the variable req_result is using a get_event_loop to perform the evaluation of the async function in a non-async environment. See this Stack Overflow answer for more details about why this is required: How does asyncio actually work?

Unfortunately, as structured, your question does not provide enough information to answer your specific point on what the difference is between the two versions and why it would occur. It may simply be a difference in when lazy expressions (such as an async function) are evaluated in other async contexts (perhaps viewing the data from the repl or in a debugger). But this is simply an off the cuff guess. But due to how you're calling the async function in your question, I figured this answer would be more valuable to you, as it answers your your implicit question ("How do I get this to work?") rather than your explicit one ("Why does this difference exist between versions?").

OmnipotentEntity
  • 16,531
  • 6
  • 62
  • 96