Προγραμματισμός

Πώς να χρησιμοποιήσετε το asyncio στο Python

Η ασύγχρονη λειτουργικότητα προγραμματισμού της Python, ή η συντομογραφία async, σας επιτρέπει να γράφετε προγράμματα που κάνουν περισσότερη δουλειά χωρίς να περιμένετε να ολοκληρωθούν ανεξάρτητες εργασίες. ο ασύγχρονο Η βιβλιοθήκη που περιλαμβάνεται στο Python σάς δίνει τα εργαλεία για να χρησιμοποιήσετε το async για την επεξεργασία δίσκου ή δικτύου I / O χωρίς να περιμένετε τα υπόλοιπα.

ασύγχρονο παρέχει δύο είδη API για την αντιμετώπιση ασύγχρονων λειτουργιών:υψηλό επίπεδο καιχαμηλό επίπεδο. Τα API υψηλού επιπέδου είναι τα πιο γενικά χρήσιμα και ισχύουν για την ευρύτερη ποικιλία εφαρμογών. Τα API χαμηλού επιπέδου είναι ισχυρά, αλλά και περίπλοκα, και χρησιμοποιούνται λιγότερο συχνά.

Θα επικεντρωθούμε στα API υψηλού επιπέδου σε αυτό το άρθρο. Στις παρακάτω ενότητες, θα ακολουθήσουμε τα πιο συχνά χρησιμοποιούμενα API υψηλού επιπέδου στοασύγχρονοκαι δείξτε πώς μπορούν να χρησιμοποιηθούν για κοινές λειτουργίες που περιλαμβάνουν ασύγχρονες εργασίες.

Εάν είστε εντελώς νέοι στο async στο Python ή αν μπορούσατε να χρησιμοποιήσετε ένα νέο για τον τρόπο λειτουργίας του, διαβάστε την εισαγωγή μου στο Python async προτού καταδυθείτε εδώ.

Εκτελέστε κορουτίνες και εργασίες στο Python

Φυσικά, η πιο κοινή χρήση για ασύγχρονο είναι να εκτελέσετε τα ασύγχρονα μέρη του σεναρίου Python. Αυτό σημαίνει ότι μαθαίνετε να εργάζεστε με κορουτίνες και εργασίες.

Τα συστατικά ασύγχρονης Python, συμπεριλαμβανομένων των κορουτίνων και των εργασιών, μπορούν να χρησιμοποιηθούν μόνο με άλλα συστατικά async και όχι με συμβατικά σύγχρονα Python, επομένως χρειάζεστεασύγχρονο να γεφυρώσει το κενό. Για να το κάνετε αυτό, χρησιμοποιείτε τοasyncio.run λειτουργία:

εισαγάγετε ασύγχρονο

async def main ():

εκτύπωση ("Περιμένει 5 δευτερόλεπτα.")

για _ στην περιοχή (5):

περιμένετε asyncio.sleep (1)

Τυπώνω (".")

εκτύπωση ("Ολοκληρώθηκε η αναμονή.")

asyncio.run (κύρια ())

Αυτό τρέχεικύριος(), μαζί με τυχόν κορουτίνεςκύριος() σβήνει και περιμένει ένα αποτέλεσμα να επιστρέψει.

Κατά γενικό κανόνα, ένα πρόγραμμα Python θα πρέπει να έχει μόνο ένα.τρέξιμο() δήλωση, ακριβώς όπως ένα πρόγραμμα Python θα πρέπει να έχει μόνο ένακύριος() λειτουργία. Το Async, εάν χρησιμοποιηθεί απρόσεκτα, μπορεί να κάνει τη ροή ελέγχου ενός προγράμματος δύσκολο να διαβαστεί. Η ύπαρξη ενός μόνο σημείου εισόδου στον κώδικα ασύγχρονης εκπομπής του προγράμματος εμποδίζει την τριχόπτωση.

Οι λειτουργίες Async μπορούν επίσης να προγραμματιστούν ωςκαθήκονταή αντικείμενα που τυλίγουν κορουτίνες και βοηθούν στην εκτέλεση τους.

async def my_task ():

Κάνε κάτι()

task = asyncio.create_task (my_task ())

my_task () Στη συνέχεια εκτελείται στο βρόχο συμβάντων, με τα αποτελέσματα να αποθηκεύονται στοέργο.

Εάν έχετε μόνο μία εργασία από την οποία θέλετε να λάβετε αποτελέσματα, μπορείτε να τη χρησιμοποιήσετεasyncio.wait_for (εργασία) για να περιμένετε να ολοκληρωθεί η εργασία και, στη συνέχεια, χρησιμοποιήστεtask.result () για να ανακτήσετε το αποτέλεσμα. Αλλά αν έχετε προγραμματίσει μια σειρά από εργασίες για εκτέλεση και θέλετε να περιμένετεόλα από αυτά να τελειώσουν, χρησιμοποιήστεasyncio.wait ([task1, task2]) για να συγκεντρώσει τα αποτελέσματα. (Λάβετε υπόψη ότι μπορείτε να ορίσετε ένα χρονικό όριο για τις λειτουργίες εάν δεν θέλετε να εκτελούνται μετά από ένα ορισμένο χρονικό διάστημα.)

Διαχειριστείτε έναν βρόχο συμβάντος ασύγχυσης στην Python

Μια άλλη κοινή χρήση γιαασύγχρονο είναι να διαχειριστεί το asyncβρόχος συμβάντος. Ο βρόχος συμβάντος είναι ένα αντικείμενο που εκτελεί συναρτήσεις ασύλληψης και επιστροφές κλήσεων. δημιουργείται αυτόματα όταν χρησιμοποιείτεasyncio.run (). Γενικά θέλετε να χρησιμοποιήσετε μόνο έναν βρόχο συμβάντος ασύγχρονου προγράμματος, και πάλι για να διατηρήσετε τα πράγματα διαχειρίσιμα.

Εάν γράφετε πιο προηγμένο λογισμικό, όπως ένας διακομιστής, θα χρειαστείτε πρόσβαση χαμηλότερου επιπέδου στον βρόχο συμβάντων. Για το σκοπό αυτό, μπορείτε να "σηκώσετε την κουκούλα" και να εργαστείτε απευθείας με τα εσωτερικά του βρόχου εκδήλωσης. Αλλά για απλές εργασίες δεν θα χρειαστεί.

Διαβάστε και γράψτε δεδομένα με ροές στο Python

Τα καλύτερα σενάρια για το async είναι μακροχρόνιες λειτουργίες δικτύου, όπου η εφαρμογή ενδέχεται να αποκλείσει την αναμονή κάποιου άλλου πόρου να επιστρέψει ένα αποτέλεσμα. Για το σκοπό αυτό,ασύγχρονο προσφέρει ροές, οι οποίοι είναι μηχανισμοί υψηλού επιπέδου για την εκτέλεση I / O δικτύου. Αυτό περιλαμβάνει τη λειτουργία ως διακομιστής για αιτήματα δικτύου.

ασύγχρονο χρησιμοποιεί δύο τάξεις,StreamReader καιStreamWriter, για ανάγνωση και εγγραφή από το δίκτυο σε υψηλό επίπεδο. Εάν θέλετε να διαβάσετε από το δίκτυο, θα το χρησιμοποιούσατεasyncio.open_connection () για να ανοίξετε τη σύνδεση. Αυτή η συνάρτηση επιστρέφει μια πλειάδαStreamReader καιStreamWriter αντικείμενα, και θα χρησιμοποιούσατε.ανάγνωση() και.γράφω() μεθόδους για κάθε επικοινωνία.

Για να λαμβάνετε συνδέσεις από απομακρυσμένους κεντρικούς υπολογιστές, χρησιμοποιήστε τοasyncio.start_server (). ο asyncio.start_server () Η συνάρτηση παίρνει ως επιχείρημα μια συνάρτηση επανάκλησης,client_connected_cb, η οποία καλείται κάθε φορά που λαμβάνει ένα αίτημα. Αυτή η συνάρτηση επανάκλησης λαμβάνει περιπτώσειςStreamReader και StreamWriter ως επιχειρήματα, ώστε να μπορείτε να χειριστείτε τη λογική ανάγνωσης / εγγραφής για το διακομιστή. (Δείτε εδώ για ένα παράδειγμα ενός απλού διακομιστή HTTP που χρησιμοποιεί τοασύγχρονο-οδηγείταιaiohttp βιβλιοθήκη.)

Συγχρονισμός εργασιών στο Python

Οι ασύγχρονες εργασίες τείνουν να εκτελούνται μεμονωμένα, αλλά μερικές φορές θα θέλετε να επικοινωνούν μεταξύ τους.ασύγχρονο παρέχει ουρές και πολλούς άλλους μηχανισμούς για συγχρονισμό μεταξύ εργασιών:

  • Ουρέςασύγχρονο Οι ουρές επιτρέπουν σε ασύγχρονες συναρτήσεις να ευθυγραμμίζουν αντικείμενα Python για κατανάλωση από άλλες λειτουργίες ασύγχρονου - για παράδειγμα, για την κατανομή φόρτου εργασίας μεταξύ διαφορετικών ειδών λειτουργιών με βάση τις συμπεριφορές τους.
  • Πρωτόγοντα συγχρονισμού: Κλειδαριές, γεγονότα, συνθήκες και σημαφοφόροι σε ασύγχρονο λειτουργούν όπως τα συμβατικά Python αντίστοιχα.

Ένα πράγμα που πρέπει να θυμάστε για όλες αυτές τις μεθόδους είναι ότι είναιδεν ασφαλές νήμα. Αυτό δεν είναι πρόβλημα για εργασίες ασύγχρονου που εκτελούνται στον ίδιο βρόχο συμβάντων. Αλλά αν προσπαθείτε να μοιραστείτε πληροφορίες με εργασίες σε διαφορετικό βρόχο συμβάντος, νήμα λειτουργικού συστήματος ή διαδικασία, θα πρέπεισπείρωμα ενότητα και τα αντικείμενά της για να το κάνει αυτό.

Επιπλέον, αν θέλετεεκτόξευση κορουτίνες πέρα ​​από τα όρια των νημάτων, χρησιμοποιήστε τοasyncio.run_coroutine_threadsafe () λειτουργία και περάστε το βρόχο συμβάντος για να το χρησιμοποιήσετε ως παράμετρο.

Σταματήστε μια κορουτίνα στο Python

Μια άλλη κοινή χρήση τουασύγχρονο, και μια υπό συζήτηση, περιμένει κάποιο αυθαίρετο χρονικό διάστημα μέσα σε μια κορουτίνα. Δεν μπορείτε να χρησιμοποιήσετεtime.sleep () για αυτό, ή θα αποκλείσετε ολόκληρο το πρόγραμμα. Αντ 'αυτού, χρησιμοποιήστεasyncio.sleep (), που επιτρέπει σε άλλες κορουτίνες να συνεχίσουν να λειτουργούν.

Χρησιμοποιήστε ασύγχρονο χαμηλότερο επίπεδο στο Python

Τέλος, αν πιστεύετε ότι ενδέχεται να απαιτείται η εφαρμογή που δημιουργείτε ασύγχρονοΤα στοιχεία χαμηλότερου επιπέδου, ρίξτε μια ματιά πριν ξεκινήσετε την κωδικοποίηση: Υπάρχει μια καλή πιθανότητα κάποιος να έχει ήδη δημιουργήσει μια βιβλιοθήκη Python με ασύγχρονη ενέργεια που κάνει ό, τι χρειάζεστε.

Για παράδειγμα, εάν χρειάζεστε ερωτήματα DNS async, ελέγξτε τοδίοδος βιβλιοθήκη, και για ασύγχρονες συνεδρίες SSH, υπάρχουνasyncSSH. Αναζητήστε το PyPI με τη λέξη-κλειδί "async" (συν άλλες λέξεις-κλειδιά που σχετίζονται με την εργασία) ή ελέγξτε τη χειροκίνητη λίστα Awesome Asyncio για ιδέες.