Το Threading μειώνει σημαντικά τον χρόνο εκτέλεσης ενός προγράμματος. Μάθετε πώς να εφαρμόζετε το threading στην Python.
Ο χρόνος εκτέλεσης είναι ένα από τα κοινά μέτρα για την αποτελεσματικότητα ενός προγράμματος. Όσο πιο γρήγορος είναι ο χρόνος εκτέλεσης τόσο καλύτερο είναι το πρόγραμμα. Το Threading είναι μια τεχνική που επιτρέπει σε ένα πρόγραμμα να εκτελεί πολλαπλές εργασίες ή διαδικασίες ταυτόχρονα.
Θα μάθετε πώς να χρησιμοποιείτε το ενσωματωμένο Python σπείρωμα ενότητα και το ταυτόχρονες.χαρακτηριστικά μονάδα μέτρησης. Και οι δύο αυτές ενότητες προσφέρουν απλούς τρόπους δημιουργίας και διαχείρισης νημάτων
Σημασία του Threading
Το Threading μειώνει τον χρόνο που χρειάζεται ένα πρόγραμμα για να ολοκληρώσει μια εργασία. Εάν η εργασία περιέχει πολλές ανεξάρτητες εργασίες, μπορείτε να χρησιμοποιήσετε το threading για να εκτελέσετε τις εργασίες ταυτόχρονα, μειώνοντας τον χρόνο αναμονής του προγράμματος για να ολοκληρωθεί μια εργασία πριν προχωρήσετε στην επόμενη.
Για παράδειγμα, ένα πρόγραμμα που κατεβάζει πολλά αρχεία εικόνας από το διαδίκτυο. Αυτό το πρόγραμμα μπορεί να χρησιμοποιήσει το threading για να κατεβάσει τα αρχεία παράλληλα και όχι ένα κάθε φορά. Αυτό εξαλείφει το χρόνο που το πρόγραμμα θα έπρεπε να περιμένει μέχρι να ολοκληρωθεί η διαδικασία λήψης ενός αρχείου πριν προχωρήσει στο επόμενο.
Αρχικό Πρόγραμμα Πριν από το Threading
Η συνάρτηση στο παρακάτω πρόγραμμα αντιπροσωπεύει μια εργασία. Η εργασία είναι να διακόψετε την εκτέλεση του προγράμματος για ένα δευτερόλεπτο. Το πρόγραμμα καλεί τη συνάρτηση δύο φορές, δημιουργώντας έτσι δύο εργασίες. Στη συνέχεια υπολογίζει το χρόνο που χρειάστηκε για να τρέξει ολόκληρο το πρόγραμμα και μετά το εμφανίζει στην οθόνη.
εισαγωγή χρόνος
start_time = time.perf_counter()
defπαύση():
Τυπώνω('Κοίμα 1 δευτερόλεπτο...')
ώρα. ύπνος(1)
Τυπώνω("Τέλος ο ύπνος...")
παύση()
παύση()
finish_time = time.perf_counter()
Τυπώνω(στ'Τελείωσε μέσα {round (finish_time - start_time, 2)} δεύτερο (α)')
Η έξοδος δείχνει ότι το πρόγραμμα χρειάστηκε 2,01 δευτερόλεπτα για να εκτελεστεί. Κάθε εργασία χρειάστηκε ένα δευτερόλεπτο και ο υπόλοιπος κώδικας χρειάστηκε 0,01 δευτερόλεπτα για να εκτελεστεί.
Μπορείτε να χρησιμοποιήσετε το threading για να εκτελέσετε ταυτόχρονα και τις δύο εργασίες. Αυτό θα πάρει και τις δύο εργασίες ένα δευτερόλεπτο για να εκτελεστούν.
Εφαρμογή Threading με χρήση της ενότητας threading
Για να τροποποιήσετε τον αρχικό κώδικα για να εφαρμόσετε το threading, εισαγάγετε το σπείρωμα μονάδα μέτρησης. Δημιουργήστε δύο νήματα, νήμα_1 και νήμα_2 χρησιμοποιώντας την Νήμα τάξη. Καλέστε το αρχή μέθοδο σε κάθε νήμα για να ξεκινήσει η εκτέλεσή του. Καλέστε το Συμμετοχή μέθοδο σε κάθε νήμα για να περιμένουμε να ολοκληρωθεί η εκτέλεσή τους πριν εκτελεστεί το υπόλοιπο πρόγραμμα.
εισαγωγή χρόνος
εισαγωγή σπείρωμα
start_time = time.perf_counter()defπαύση():
Τυπώνω('Κοίμα 1 δευτερόλεπτο...')
ώρα. ύπνος(1)
Τυπώνω("Τέλος ο ύπνος...")νήμα_1 = σπείρωμα. Νήμα (στόχος=παύση)
νήμα_2 = σπείρωμα. Νήμα (στόχος=παύση)thread_1.start()
thread_2.start()thread_1.join()
thread_2.join()
finish_time = time.perf_counter()
Τυπώνω(στ'Τελείωσε μέσα {round (finish_time - start_time, 2)} δεύτερο (α)')
Το πρόγραμμα θα τρέξει και τα δύο νήματα ταυτόχρονα. Αυτό θα μειώσει τον χρόνο που απαιτείται για την ολοκλήρωση και των δύο εργασιών.
Η έξοδος δείχνει ότι ο χρόνος που απαιτείται για την εκτέλεση των ίδιων εργασιών είναι περίπου ένα δευτερόλεπτο. Αυτός είναι ο μισός χρόνος που χρειάστηκε το αρχικό πρόγραμμα.
Εφαρμογή Threading με χρήση της ενότητας concurrent.futures
Η Python 3.2 είδε την εισαγωγή του ταυτόχρονες.μέλλουσες μονάδα μέτρησης. Αυτή η ενότητα παρέχει μια διεπαφή υψηλού επιπέδου για την εκτέλεση ασύγχρονων εργασιών χρησιμοποιώντας νήματα. Παρέχει έναν απλούστερο τρόπο για την παράλληλη εκτέλεση εργασιών.
Για να τροποποιήσετε το αρχικό πρόγραμμα ώστε να χρησιμοποιεί νήματα, εισαγάγετε τη λειτουργική μονάδα concurrent.features. Χρησιμοποιήστε το ThreadPoolExecutor κλάση από την ενότητα concurrent.futures για να δημιουργήσετε μια ομάδα νημάτων. Υποβάλετε το παύση λειτουργήσει στην πισίνα δύο φορές. ο υποβάλλουν η μέθοδος επιστρέφει α μελλοντικός αντικείμενο που αντιπροσωπεύει το αποτέλεσμα της κλήσης συνάρτησης.
Επαναλάβετε πάνω από το συμβόλαια μελλοντικής εκπλήρωσης και εκτυπώστε τα αποτελέσματά τους χρησιμοποιώντας το αποτέλεσμα μέθοδος.
εισαγωγή χρόνος
εισαγωγή ταυτόχρονες.μέλλουσεςstart_time = time.perf_counter()
defπαύση():
Τυπώνω('Κοίμα 1 δευτερόλεπτο...')
ώρα. ύπνος(1)
ΕΠΙΣΤΡΟΦΗ"Τέλος ο ύπνος..."με ταυτόχρονες.μέλλουσες. ThreadPoolExecutor() όπως και εκτελεστής διαθήκης:
αποτελέσματα = [executor.submit (pause) Για _ σε εύρος(2)]
Για φά σε concurrent.futures.as_completed (αποτελέσματα):
εκτύπωση (f.result())finish_time = time.perf_counter()
Τυπώνω(στ'Τελείωσε μέσα {round (finish_time - start_time, 2)} δεύτερο (α)')
Η ενότητα concurrent.features φροντίζει να ξεκινά και να ενώνει τα νήματα για εσάς. Αυτό κάνει τον κωδικό σας πιο καθαρό.
Η έξοδος είναι πανομοιότυπη με αυτή της μονάδας threading. Η ενότητα threading είναι χρήσιμη για απλές περιπτώσεις όπου χρειάζεται να εκτελέσετε μερικά νήματα παράλληλα. Από την άλλη πλευρά, η ενότητα concurrent.futures είναι χρήσιμη για πιο περίπλοκες περιπτώσεις όπου χρειάζεται να εκτελέσετε πολλές εργασίες ταυτόχρονα.
Χρήση Threading σε πραγματικό σενάριο
Η χρήση νημάτων για την εκτέλεση του παραπάνω προγράμματος μείωσε τον χρόνο κατά ένα δευτερόλεπτο. Στον πραγματικό κόσμο, τα νήματα εξοικονομούν περισσότερο χρόνο. Δημιουργήστε ένα πρόγραμμα που κατεβάζει εικόνες από το διαδίκτυο. Ξεκινήστε από δημιουργώντας ένα νέο εικονικό περιβάλλον. Εκτελέστε την ακόλουθη εντολή στο τερματικό για να εγκαταστήσετε το αιτήσεων βιβλιοθήκη:
αιτήματα εγκατάστασης pip
Η βιβλιοθήκη αιτημάτων θα σας επιτρέψει να στείλετε αιτήματα HTTP. Εισαγάγετε τη βιβλιοθήκη αιτημάτων και τη βιβλιοθήκη χρόνου.
εισαγωγή αιτήσεων
εισαγωγή χρόνος
Δημιουργήστε μια λίστα με διευθύνσεις URL των εικόνων που θέλετε να κατεβάσετε. Αφήστε τα να είναι τουλάχιστον δέκα, ώστε να μπορείτε να παρατηρήσετε μια σημαντική διαφορά όταν εφαρμόζετε το threading.
img_urls = [
' https://images.unsplash.com/photo-1524429656589-6633a470097c',
' https://images.unsplash.com/photo-1530224264768-7ff8c1789d79',
' https://images.unsplash.com/photo-1564135624576-c5c88640f235',
' https://images.unsplash.com/photo-1541698444083-023c97d3f4b6',
' https://images.unsplash.com/photo-1522364723953-452d3431c267',
' https://images.unsplash.com/photo-1513938709626-033611b8cc03',
' https://images.unsplash.com/photo-1507143550189-fed454f93097',
' https://images.unsplash.com/photo-1493976040374-85c8e12f0c0e',
' https://images.unsplash.com/photo-1504198453319-5ce911bafcde',
' https://images.unsplash.com/photo-1530122037265-a5f1f91d3b99',
' https://images.unsplash.com/photo-1516972810927-80185027ca84',
' https://images.unsplash.com/photo-1550439062-609e1531270e',
]
Κάντε βρόχο στη λίστα URL που κατεβάζουν κάθε εικόνα στον ίδιο φάκελο που περιέχει το έργο σας. Εμφανίστε το χρόνο που απαιτείται για τη λήψη των εικόνων αφαιρώντας τον χρόνο τερματισμού από την ώρα έναρξης.
start_time = time.perf_counter()
Για img_url σε img_urls:
img_bytes = requests.get (img_url).content
img_name = img_url.split('/')[3]
img_name = φά'{img_name}.jpg'
με άνοιγμα (img_name, 'wb') όπως και img_file:
img_file.write (img_bytes)
Τυπώνω(φά'{img_name} έγινε λήψη...')
finish_time = time.perf_counter()
Τυπώνω(στ'Τελείωσε μέσα {finish_time - start_time} δευτερόλεπτα')
Το πρόγραμμα χρειάζεται περίπου 22 δευτερόλεπτα για τη λήψη των 12 εικόνων. Μπορεί να διαφέρει για εσάς, καθώς ο χρόνος που απαιτείται για τη λήψη των εικόνων εξαρτάται επίσης από την ταχύτητα του διαδικτύου σας.
Τροποποιήστε το πρόγραμμα για να χρησιμοποιήσετε το threading χρησιμοποιώντας τη λειτουργική μονάδα concurrent.features. Αντί για βρόχο, χρησιμοποιήστε μια συνάρτηση. Αυτή είναι η λειτουργία που θα περάσετε στο εκτελεστής διαθήκης παράδειγμα.
εισαγωγή αιτήσεων
εισαγωγή χρόνος
εισαγωγή ταυτόχρονες.μέλλουσεςimg_urls = [
' https://images.unsplash.com/photo-1524429656589-6633a470097c',
' https://images.unsplash.com/photo-1530224264768-7ff8c1789d79',
' https://images.unsplash.com/photo-1564135624576-c5c88640f235',
' https://images.unsplash.com/photo-1541698444083-023c97d3f4b6',
' https://images.unsplash.com/photo-1522364723953-452d3431c267',
' https://images.unsplash.com/photo-1513938709626-033611b8cc03',
' https://images.unsplash.com/photo-1507143550189-fed454f93097',
' https://images.unsplash.com/photo-1493976040374-85c8e12f0c0e',
' https://images.unsplash.com/photo-1504198453319-5ce911bafcde',
' https://images.unsplash.com/photo-1530122037265-a5f1f91d3b99',
' https://images.unsplash.com/photo-1516972810927-80185027ca84',
' https://images.unsplash.com/photo-1550439062-609e1531270e',
]start_time = time.perf_counter()
defλήψη_εικόνας(img_url):
img_bytes = requests.get (img_url).content
img_name = img_url.split('/')[3]
img_name = φά'{img_name}.jpg'
με άνοιγμα (img_name, 'wb') όπως και img_file:
img_file.write (img_bytes)
Τυπώνω(φά'{img_name} έγινε λήψη...')με ταυτόχρονες.μέλλουσες. ThreadPoolExecutor() όπως και εκτελεστής διαθήκης:
executor.map (download_image, img_urls)finish_time = time.perf_counter()
Τυπώνω(στ'Τελείωσε μέσα {finish_time-start_time} δευτερόλεπτα')
Μετά την εισαγωγή του νήματος. Ο χρόνος μειώνεται σημαντικά. Χρειάστηκαν μόνο 4 δευτερόλεπτα για να ολοκληρωθεί η εκτέλεση του προγράμματος.
Σενάρια κατάλληλα για νήμα
Μερικά από τα σενάρια που είναι κατάλληλα για νήμα είναι:
- Εργασίες με δέσμευση εισόδου/εξόδου: Εάν το πρόγραμμα αφιερώνει το μεγαλύτερο μέρος του χρόνου περιμένοντας να ολοκληρωθούν οι λειτουργίες εισόδου ή εξόδου. Το Threading μπορεί να βελτιώσει την απόδοση επιτρέποντας σε άλλες εργασίες να εκτελεστούν ενώ περιμένει να ολοκληρωθούν οι λειτουργίες I/O.
- Απόξεση ιστού: Η απόξεση ιστού περιλαμβάνει την υποβολή αιτημάτων HTTP και την ανάλυση αποκρίσεων HTML. Το Threading βοηθά στην επιτάχυνση της διαδικασίας, επιτρέποντάς σας να κάνετε πολλά αιτήματα ταυτόχρονα.
- Εργασίες που συνδέονται με την CPU: Το Threading μπορεί να βοηθήσει στη βελτίωση της απόδοσης επιτρέποντας την παράλληλη εκτέλεση πολλαπλών εργασιών.
Εξοικειωθείτε με το Threading σε άλλες γλώσσες
Η Python δεν είναι η μόνη γλώσσα που υποστηρίζει threading. Οι περισσότερες γλώσσες προγραμματισμού υποστηρίζουν κάποια μορφή νήματος. Είναι σημαντικό να εξοικειωθείτε με την υλοποίηση νημάτων σε άλλες γλώσσες. Αυτό σας εξοπλίζει με τις απαραίτητες δεξιότητες για να αντιμετωπίσετε διαφορετικά σενάρια όπου μπορεί να εφαρμοστεί το threading.