async versus sync

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
davef
Posts: 811
Joined: Thu Apr 30, 2020 1:03 am
Location: Christchurch, NZ

async versus sync

Post by davef » Sun Feb 28, 2021 10:42 pm

Think I have finally come across a useful explanation of why I had to sprinkle some utime.sleep() calls when doing some things internet related.

From https://blog.miguelgrinberg.com/post/mi ... -the-cloud
A Wi-Fi connection can take a few seconds to be completed, and this happens asynchronously. To avoid returning from this function before the connection is fully established, I've added a while-loop that blocks the function until the isconnected() function returns True. Inside the loop I just call time.sleep(1) to wait for one second before checking the connection again. Using a while-loop with a sleep inside is a standard way to block until a condition is satisfied.
My question is how do I find out which functions are asynchronous? What about:
- ntptime.time()
- ntptime.settime()
- addr = usocket.getaddrinfo(host, port)[0][-1]
- sock.connect(addr)

Thanks in advance.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: async versus sync

Post by pythoncoder » Mon Mar 01, 2021 12:20 pm

I think there is some confusion over terminology. In Python an asynchronous function is one defined with

Code: Select all

async def foo():
    # funtcion body
Such functions (or methods) can run concurrently as tasks under asyncio (uasyncio in MicroPython).

As far as I know, no official library other than uasyncio currently defines asynchronous functions. The examples you quote are definitely synchronous.

However the internet is not strictly synchronous. It can suffer arbitrarily long latency depending on the route to the other endpoint. Depending on protocol, it can suffer missed packets (UDP).

Individual net-facing functions behave in different ways, which you can discover from the docs or from the source. Consider ntptime.time(): source here. It has a 1 second timeout. For obvious reasons, if an NTP query suffers a 20s latency the result isn't much use. In practice this means it sometimes fails so you need to check for that. .settitme() is fast. getaddrinfo() can block for some time depending on how quickly the DNS server responds. socket.connect() can take time. I can't remember if it has a timeout. In general all internet facing methods need exception trapping.
Peter Hinch
Index to my micropython libraries.

davef
Posts: 811
Joined: Thu Apr 30, 2020 1:03 am
Location: Christchurch, NZ

Re: async versus sync

Post by davef » Mon Mar 01, 2021 5:46 pm

Thank you Peter for taking the time to provide a helpful explanation. Error trapping is one issue, handling the errors without doing a machine.reset() is my current focus.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: async versus sync

Post by pythoncoder » Tue Mar 02, 2021 1:45 pm

It's hard to comment without knowing more. In my work on asynchronous internet facing systems I've never needed to reset the machine. You should always be able to recover from exceptions without needing to do anything this radical.

You might like to look at micropython-mqtt or micropython-iot for examples of libraries capable of recovering from a wide variety of errors.
Peter Hinch
Index to my micropython libraries.

davef
Posts: 811
Joined: Thu Apr 30, 2020 1:03 am
Location: Christchurch, NZ

Re: async versus sync

Post by davef » Wed Mar 03, 2021 7:27 am

I had a closer look at your resilient code but to be honest I have never used a thread or written anything asynchronous. It looks like a serious bit of work, one that would be a challenge to get this guy's head around.

At the moment I get a reliable WiFi connection, NTP time acquisition and access to Gmail's SMTP server without resorting to machine.resets() ... they are there just to make sure the system doesn't die.

I'll try to determine if there is a small project I could try uasynco on.

Thanks for the encouragement.

davef
Posts: 811
Joined: Thu Apr 30, 2020 1:03 am
Location: Christchurch, NZ

Re: async versus sync

Post by davef » Tue May 25, 2021 3:14 am

My current understanding:
- socket.getaddrinfo() is a blocking call. It either returns the address or error messages.
- socket.connect() is a blocking call. Don't know about it returning error messages (yet).

But what is network.WLAN(network.STA_IF).connect() if you have to wait, after returning from the call,
until the connection is fully-established? Can you say it is a non-blocking call or is there a
special term for going through the:

Code: Select all

        while not sta_if.isconnected():
            print('.', end = '')
            utime.sleep(1)

process?

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: async versus sync

Post by pythoncoder » Tue May 25, 2021 5:29 am

The .connect() call is non-blocking. Because connection can take time, you need to delay before you can assume a connection. You test for this by periodically calling the non-blocking .isconnected().

In asynchronous code you would use await asyncio.sleep(1) in place of utime.sleep(1).
Peter Hinch
Index to my micropython libraries.

davef
Posts: 811
Joined: Thu Apr 30, 2020 1:03 am
Location: Christchurch, NZ

Re: async versus sync

Post by davef » Tue May 25, 2021 6:48 am

Thanks for responding.

To confirm:
network.WLAN(network.STA_IF).connect() and usocket.connect() are both non-blocking. If I want to wait for a call to usocket.connect() to complete what do I do? I did a dir(usocket) and don't see a isconnected() method.

Also, tried usocket.isconnected() and got:

Code: Select all

AttributeError: 'socket' object has no attribute 'isconnected'
At one stage I had lots of utime.sleep(1)s sprinkled through uMail's socket code to try to improve connection success.

I get a feeling I had better take the leap and give asyncio a go.

Cheers

Post Reply