Async Python Tutorial: Foundations for those with no prior async experience

preview_player
Показать описание
Are you new to asynchronous programming? Are you past the novice python material and looking to increase your knowledge and experience of python in a variety of contexts? You've come to the right place. This tutorial on the foundations of Python coroutines in order to understand async programming is the first of a two part tutorial.

Please use Python 3.74+
Рекомендации по теме
Комментарии
Автор

If you found this tutorial useful in any way, consider subscribing to show your support for the channel. We've got some really exciting content in the pipeline which we can't wait to release!

LivePython
Автор

Need to write code using async
me at 9AM: Let me go through this 15min video to refresh my knowledge
me at 5PM: Let me finish going through this 15min video before I leave for the day.

nithinchinni
Автор

I’m only 4 minutes in and my mind has been blown by using yield on the right side of the expression... python continues to amaze me during my 3rd year learning it

bmorr
Автор

It's interesting to go over the python mechanics of coroutines, but is it really the easiest step to take 1st? Wouldn't it make sense to start with what async achieve and how it behave (from the user perspective)?

osquigene
Автор

Excellent and Great information. A bit of constructive criticism. There are no fullstops or pauses when switching from one sentence to the next. Pauses at the right place naturally indicates that a sentence has finished so our brain can process it and store it and get ready for the next sentence.

cooleo
Автор

I liked the way you explained async/await with simple examples. Waiting for the next parts in this series. Thanks :)

rajeshkab
Автор

You are definitely very knowledgeable, but you should explain first, yield and coroutines in another video, because it is too short on this one

georgesmith
Автор

Liked the video, thank you so much for the explanation. Subscribed to your channel

RN-ermz
Автор

This channel is sooo underrated, good content 💥

vihnupradeep
Автор

Judit Polgar in the house! :D celebrating your comparison..!

markushinterthan
Автор

16:08, the output of outer() does not include the desired final statement indicating the results of phase1 and phase2. You could replace 'return result1, resul2' in line 11 with something that prints the fully awaited results, like print('phase1:', result1, 'phase2:', result2) ?

BaritoneAZ
Автор

Thx a lot for this tutorial! it would be nice if you can provide a Github repo with all codes from your tutorials

hermesmercuriustrismegistu
Автор

I've trying to save (to a file) AND plot the strings received from the (py)serial port, real-time, that come in every 500ms..

However, when I plot, it apparently takes too long, and I start losing data (in the CSV and plot) after just a few seconds! I don't want to make this too complicated, but not sure if I should be looking at queues/collections.deque, threads, or some other package like 'oscilloscope' or 'pydatascope'. Any suggestions?

import tkinter as Tkinter
import time
import threading
import random
import queue as Queue
import serial
import RPi.GPIO as GPIO

ser = serial.Serial('/dev/ttyACM0', 9600)

GPIO.setmode(GPIO.BOARD)
GPIO.setup(33, GPIO.OUT)
GPIO.output(33, GPIO.HIGH)

def ledON5():
print("LED BUTTON PRESSED")
if GPIO.input(33):
GPIO.output(33, GPIO.LOW)
print("LED BUTTON aan")
else:
GPIO.output(33, GPIO.HIGH)
print("LED BUTTON uit")

class GuiPart:
def __init__(self, master, queue, endCommand):
self.queue = queue
# Set up the GUI
console = Tkinter.Button(master, text='relais 5', command=ledON5)
console.place(x=30, y=30)
#master.title("Test")
root.title("Title")
root.geometry('800x480')
root.configure(bg='white')
label1 = Tkinter.Label(master, text="counter", bg='white', fg="green")
label1.place(x=60, y=60)
#label1["text"]=msg
# Add more GUI stuff here depending on your specific needs

def processIncoming(self):
"""Handle all messages currently in the queue, if any."""
while self.queue.qsize( ):
try:
msg = self.queue.get(0)

# Check contents of message and do whatever is needed. As a
# simple test, print it (in real life, you would
# suitably update the GUI's display in a richer fashion).
print(msg)
except Queue.Empty:
# just on general principles, although we don't
# expect this branch to be taken in this case
pass

class ThreadedClient:
"""
Launch the main part of the GUI and the worker thread. periodicCall and
endApplication could reside in the GUI part, but putting them here
means that you have all the thread controls in a single place.
"""
def __init__(self, master):
"""
Start the GUI and the asynchronous threads. We are in the main
(original) thread of the application, which will later be used by
the GUI as well. We spawn a new thread for the worker (I/O).
"""
self.master = master

# Create the queue
self.queue = Queue.Queue( )

# Set up the GUI part
self.gui = GuiPart(master, self.queue, self.endApplication)

# Set up the thread to do asynchronous I/O
# More threads can also be created and used, if necessary
self.running = 1
self.thread1 =
self.thread1.start( )

# Start the periodic call in the GUI to check if the queue contains
# anything
self.periodicCall( )

def periodicCall(self):
"""
Check every 200 ms if there is something new in the queue.
"""
self.gui.processIncoming( )
if not self.running:
# This is the brutal stop of the system. You may want to do
# some cleanup before actually shutting it down.
import sys
sys.exit(1)
self.master.after(200, self.periodicCall)

def workerThread1(self):
"""
This is where we handle the asynchronous I/O. For example, it may be
a 'select( )'. One important thing to remember is that the thread has
to yield control pretty regularly, by select or otherwise.
"""
while True:
# To simulate asynchronous I/O, we create a random number at
# random intervals. Replace the following two lines with the real
# thing.
time.sleep(1)
#msg = "OK"
msg1 = ser.readline()
msg = msg1.decode().strip()
self.queue.put(msg)

def endApplication(self):
self.running = 0

rand = random.Random( )
root = Tkinter.Tk( )


client = ThreadedClient(root)
root.mainloop( )





import Tkinter
import time
import threading
import random
import Queue

class GuiPart:
def _ _init_ _(self, master, queue, endCommand):
self.queue = queue
# Set up the GUI
console = Tkinter.Button(master, text='Done', command=endCommand)
console.pack( )
# Add more GUI stuff here depending on your specific needs

def processIncoming(self):
"""Handle all messages currently in the queue, if any."""
while self.queue.qsize( ):
try:
msg = self.queue.get(0)
# Check contents of message and do whatever is needed. As a
# simple test, print it (in real life, you would
# suitably update the GUI's display in a richer fashion).
print msg
except Queue.Empty:
# just on general principles, although we don't
# expect this branch to be taken in this case
pass

class ThreadedClient:
"""
Launch the main part of the GUI and the worker thread. periodicCall and
endApplication could reside in the GUI part, but putting them here
means that you have all the thread controls in a single place.
"""
def _ _init_ _(self, master):
"""
Start the GUI and the asynchronous threads. We are in the main
(original) thread of the application, which will later be used by
the GUI as well. We spawn a new thread for the worker (I/O).
"""
self.master = master

# Create the queue
self.queue = Queue.Queue( )

# Set up the GUI part
self.gui = GuiPart(master, self.queue, self.endApplication)

# Set up the thread to do asynchronous I/O
# More threads can also be created and used, if necessary
self.running = 1
self.thread1 =
self.thread1.start( )

# Start the periodic call in the GUI to check if the queue contains
# anything
self.periodicCall( )

def periodicCall(self):
"""
Check every 200 ms if there is something new in the queue.
"""
self.gui.processIncoming( )
if not self.running:
# This is the brutal stop of the system. You may want to do
# some cleanup before actually shutting it down.
import sys
sys.exit(1)
self.master.after(200, self.periodicCall)

def workerThread1(self):
"""
This is where we handle the asynchronous I/O. For example, it may be
a 'select( )'. One important thing to remember is that the thread has
to yield control pretty regularly, by select or otherwise.
"""
while self.running:
# To simulate asynchronous I/O, we create a random number at
# random intervals. Replace the following two lines with the real
# thing.
time.sleep(rand.random( ) * 1.5)
msg = rand.random( )
self.queue.put(msg)

def endApplication(self):
self.running = 0

rand = random.Random( )
root = Tkinter.Tk( )

client = ThreadedClient(root)
root.mainloop( )

bennguyen
Автор

1 quick question:
Is it possible to run a blocking code in non blocking way?

def network_request(data):
# blocking code
print(f"iniating {data}")
sleep(10)
# intentionally used rather than asyncio version
print(data + random())
return data + random()

async def async_wrapper(data):
return await network_request(data)


async def main():
# await asyncio.gather(network_request(1), network_request(3), network_request(5))
await asyncio.gather(async_wrapper(1), async_wrapper(3), async_wrapper(5))

asyncio.run(main())

arnabmukherjee
Автор

My point is why do you write a code which is very hard to maintain?

piby
Автор

Hey im not really aware of the new functions in python and some of the constructs. When is an async design preferred over a threaded approach?

Coach-Solar_Hound
Автор

Is there no other way to wrangle in multiple functions other than gathering them by name each time (looking at gather.count() example)

HeavensMeat
Автор

It sounds like some kind of AI voice is trying to teach me async programming. I love it

umut
Автор

Great video! I hope you'll release more on async soon :3

arthurh
Автор

1. mixes up coroutines and generators
2. warns me not to confuse coroutines and generators
3. continues to mix them up

elfab
join shbcf.ru