Closed GM-Script-Writer-62850 closed 1 month ago
Thanks @GM-Script-Writer-62850 -- this is neat and definitely supporting a more full-featured asyncio http client is something we need for MicroPython.
I'm not sure adding an async version of urequests
makes sense though if the library it's based on (requests
-- https://requests.readthedocs.io/en/latest/) doesn't itself support asyncio.
I think the effort would be better spent turning this into a micro implementation of aiohttp
(or any of the other asyncio-based Python http libraries).
i did look at this one, but it did not look to support sending post data (massive deal breaker for my use case) https://github.com/micropython/micropython-lib/blob/master/micropython/uaiohttpclient/uaiohttpclient.py in my current project i only make a single GET request at boot, i use POST for sending data to log and backing up config data
aiohttp.request("POST", url)
now how do i send data? i have a URL and a method, but no way to send post data
and what about setting the content type header (eg: application/x-www-form-urlencoded
or applicatoion/json
)?
Errr, umm, yes, that seems distinctly unimplemented. 🙄
i realized today i could also just make a non-blocking post request that will be delayed till my sleep call happens
async def post(json_str,comment=""):
await sleep(0)
r=urequests.post(config.remote_url,data=json_str,headers={"Content-type":"application/json"})
if r.status_code != 200:
print("------ERROR------")
# probably should log a few errors in memory so i can check if there are errors occurring later
print(comment,r.status_code,"-", r.content)
r.close()
uasyncio.create_task(post(data,"Update backup config data:"))
Could combine this with my modded uasyncio_urequests
lib, just not sure if it is even a good idea to make it possible to have multiple open requests while at the same time having a web server process running as the same time (i think the pico w has a limit of 4 open sockets)
This is not a non-blocking post request. It's just a deferred post request that is still blocking. Your event loop will still pause while one HTTP request happens and there will only be one concurrent request.
i know it is just deferred, i am just not sure it would be a good idea to do it truly non-blocking, in my use case this would max at 2 post request running at the same time
the way my code is setup i have a entire 2 seconds to make post request w/out interfering with any other code execution at all (baring once a day events and a client actively connected) and this window will be followed by a 750ms window
things to consider:
@GM-Script-Writer-62850 FYI, I am looking for an asyncio
http client so found this and tried it out but it does not actually do the requests in parallel. It works the same as ordinary requests
.
@bulletmark @GM-Script-Writer-62850 you may want to try this #752, just remove ssl=...
parameter in
..
reader, writer = await asyncio.open_connection(host, port, ssl=ssl)
...
and it should work 👍🏼, e.g.
import uaiohttpclient as aiohttp
import asyncio
async def fetch(client):
async with client.get("http://micropython.org") as resp:
assert resp.status == 200
return await resp.text()
async def main():
async with aiohttp.ClientSession() as client:
html = await fetch(client)
print(html.decode())
if __name__ == "__main__":
asyncio.run(main())
@GM-Script-Writer-62850 @Carglglz After removing that ssl
parameter that new version does work on MicroPython and the requests are correctly done in parallel.
However, after failing with that earlier I went back to the standard uaiohttpclient
from micropython-lib
which had not worked for me and I discovered a simple bug so I am back to using that. I submitted a PR with that fix.
@GM-Script-Writer-62850 BTW, you could actually remove the async
and await
from each of the 6 wrapper functions at the bottom to make it slightly more efficient. Those stubs would simply then return the coroutine directly to be awaited by the caller.
There is now a quite full featured HTTP client in aiohttp
. I believe that serves the purpose discussed here. And that the existing requests
library does not need to be asyncified, considering that there is another library.
Note that aiohttp
is not shipped with:
MicroPython v1.24.0-preview.224.g6c3dc0c0b on 2024-08-22; Raspberry Pi Pico W with RP2040
help('modules')
__main__ asyncio/__init__ hashlib rp2
_asyncio asyncio/core heapq select
_boot asyncio/event io socket
_boot_fat asyncio/funcs json ssl
_onewire asyncio/lock lwip struct
_rp2 asyncio/stream machine sys
_thread binascii math time
_webrepl bluetooth micropython tls
aioble/__init__ builtins mip/__init__ uasyncio
aioble/central cmath neopixel uctypes
aioble/client collections network urequests
aioble/core cryptolib ntptime vfs
aioble/device deflate onewire webrepl
aioble/l2cap dht os webrepl_setup
aioble/peripheral ds18x20 platform websocket
aioble/security errno random
aioble/server framebuf re
array gc requests/__init__
Plus any modules on the filesystem
aiohttp
is in micropython-lib and can be installed with mip: > mpremote mip install aiohttp
.
Patch: urequests.zip Attachment includes both before/after scripts of the current version of urequests as well as a
diff.patch
file This also includes a copy of this with the patch applied for issue #546Using this test code shows my uasyncio urequests patch works