Threading значително намалява времето за изпълнение на програмата. Научете как да прилагате нишки в Python.

Времето за изпълнение е една от често срещаните мерки за ефективността на една програма. Колкото по-бързо е времето за изпълнение, толкова по-добра е програмата. Threading е техника, която позволява на програмата да изпълнява множество задачи или процеси едновременно.

Ще научите как да използвате вградения Python резба модул и concurrent.features модул. И двата модула предлагат прости начини за създаване и управление на нишки

Значение на Threading

Threading намалява времето, необходимо на програмата за завършване на задача. Ако заданието съдържа множество независими задачи, можете да използвате нишки, за да изпълнявате задачите едновременно, намалявайки времето за изчакване на програмата, за да завърши една задача, преди да преминете към следващата.

Например програма, която изтегля множество файлове с изображения от интернет. Тази програма може да използва нишки за изтегляне на файловете паралелно, а не един по един. Това елиминира времето, което програмата ще трябва да изчака процеса на изтегляне на един файл да завърши, преди да премине към следващия.

instagram viewer

Първоначална програма преди резба

Функцията в следната програма представлява задача. Задачата е да спрете изпълнението на програмата за една секунда. Програмата извиква функцията два пъти, като по този начин създава две задачи. След това изчислява времето, необходимо за изпълнение на цялата програма, и след това го показва на екрана.

импортиране време

start_time = time.perf_counter()

дефпауза():
печат („Спя 1 секунда...“)
time.sleep(1)
печат („Край със съня...“)

пауза()
пауза()
край_време = време.perf_counter()
печат (f'Finished in {кръг (край_час - начален_час, 2)} секунда (и)')

Резултатът показва, че изпълнението на програмата е отнело 2,01 секунди. Всяка задача отне една секунда, а останалата част от кода отне 0,01 секунди за изпълнение.

Можете да използвате нишки за едновременно изпълнение на двете задачи. Това ще отнеме и двете задачи по една секунда за изпълнение.

Внедряване на Threading с помощта на модула Threading

За да промените първоначалния код за прилагане на нишки, импортирайте резба модул. Създайте две нишки, нишка_1 и нишка_2 използвайки Нишка клас. Обадете се на започнете метод на всяка нишка, за да започне нейното изпълнение. Обадете се на присъединяване метод на всяка нишка, за да изчака тяхното изпълнение да завърши, преди да се изпълни останалата част от програмата.

импортиране време
импортиране резба
start_time = time.perf_counter()

дефпауза():
печат („Спя 1 секунда...“)
time.sleep(1)
печат („Край със съня...“)

резба_1 = резба. Нишка (цел=пауза)
резба_2 = резба. Нишка (цел=пауза)

thread_1.start()
thread_2.start()

thread_1.join()
thread_2.join()

край_време = време.perf_counter()
печат (f'Finished in {кръг (край_час - начален_час, 2)} секунда (и)')

Програмата ще изпълнява и двете нишки едновременно. Това ще намали времето, необходимо за изпълнение на двете задачи.

Резултатът показва, че времето, необходимо за изпълнение на същите задачи, е около секунда. Това е половината от времето, което отне първоначалната програма.

Внедряване на Threading с помощта на модула concurrent.futures

Python 3.2 видя въвеждането на едновременни.фючърси модул. Този модул предоставя интерфейс от високо ниво за изпълнение на асинхронни задачи с помощта на нишки. Той предоставя по-лесен начин за паралелно изпълнение на задачи.

За да модифицирате първоначалната програма за използване на нишки, импортирайте модула concurrent.features. Използвай ThreadPoolExecutor клас от модула concurrent.futures за създаване на набор от нишки. Изпратете пауза функция към басейна два пъти. The Изпращане метод връща a бъдеще обект, който представлява резултата от извикването на функцията.

Повторете върху фючърси и отпечатайте техните резултати с помощта на резултат метод.

импортиране време
импортиране едновременни.фючърси

start_time = time.perf_counter()

дефпауза():
печат („Спя 1 секунда...“)
time.sleep(1)
връщане„Край със съня...“

с едновременни.фючърси. ThreadPoolExecutor() като изпълнител:
резултати = [executor.submit (пауза) за _ в диапазон (2)]
за f в concurrent.futures.as_completed (резултати):
печат (f.result())

край_време = време.perf_counter()

печат (f'Finished in {кръг (край_час - начален_час, 2)} секунда (и)')

Модулът concurrent.features се грижи за стартирането и присъединяването към нишките вместо вас. Това прави вашия код по-чист.

Резултатът е идентичен с този на резбовия модул. Модулът за нишки е полезен за прости случаи, когато трябва да стартирате няколко нишки паралелно. От друга страна, модулът concurrent.futures е полезен за по-сложни случаи, когато трябва да изпълнявате много задачи едновременно.

Използване на Threading в сценарий от реалния свят

Използването на нишки за изпълнение на горната програма намали времето с една секунда. В реалния свят нишките спестяват повече време. Създайте програма, която изтегля изображения от интернет. Започнете от създаване на нова виртуална среда. Изпълнете следната команда в терминала, за да инсталирате заявки библиотека:

заявки за инсталиране на pip

Библиотеката с заявки ще ви позволи да изпращате HTTP заявки. Импортирайте библиотеката със заявки и библиотеката с време.

импортиране заявки
импортиране време

Създайте списък с URL адреси на изображенията, които искате да изтеглите. Нека са поне десет, за да можете да забележите значителна разлика, когато прилагате нишки.

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).съдържание
img_name = img_url.split('/')[3]
img_name = е'{img_name}.jpg'
с отворено (img_name, "wb") като img_file:
img_file.write (img_bytes)
печат (е'{img_name} беше изтеглен...')
край_време = време.perf_counter()
печат (f'Finished in {finish_time - start_time} секунди)

Програмата отнема около 22 секунди, за да изтегли 12-те изображения. Може да варира за вас, тъй като времето, необходимо за изтегляне на изображенията, също зависи от скоростта на вашия интернет.

Променете програмата, за да използвате нишки с помощта на модула 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()

дефизтегляне_изображение(img_url):
img_bytes = requests.get (img_url).съдържание
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 (изтегляне_изображение, img_urls)

край_време = време.perf_counter()

печат (f'Finished in {finish_time-start_time} секунди)

След въвеждане на резба. Времето значително намалява. Отне само 4 секунди, за да завърши изпълнението на програмата.

Сценарии, подходящи за Threading

Някои от сценариите, подходящи за нишки, са:

  • I/O обвързани задачи: Ако програмата прекарва по-голямата част от времето в изчакване за завършване на входни или изходни операции. Threading може да подобри производителността, като позволи на други задачи да се изпълняват, докато чакат I/O операциите да завършат.
  • Уеб скрапинг: Уеб скрапирането включва правене на HTTP заявки и анализиране на HTML отговори. Threading помага за ускоряване на процеса, като ви позволява да правите множество заявки едновременно.
  • Задачи, свързани с процесора: Нишките могат да помогнат за подобряване на производителността, като позволяват множество задачи да се изпълняват паралелно.

Запознайте се с Threading на други езици

Python не е единственият език, който поддържа нишки. Повечето езици за програмиране поддържат някаква форма на резба. Важно е да се запознаете с изпълнението на нишки на други езици. Това ви предоставя необходимите умения за справяне с различни сценарии, при които може да се прилага нишка.