Асинхронное программирование в python

Модули потоковой передачи

Модуль потоковой передачи — это высокоуровневая реализация многопоточности, используемая для развертывания приложения на Python. Чтобы использовать многопоточность, нам нужно импортировать модуль  threading в программу Python.

Методы класса потока

Методы Описание
start() Метод start() используется для инициирования активности потока. И он вызывается только один раз для каждого потока, чтобы можно было начать выполнение потока.
run() Метод run() используется для определения активности потока и может быть переопределен классом, расширяющим класс потоков.
join() Метод join() используется для блокировки выполнения другого кода до завершения потока.

Выполните следующие шаги, чтобы реализовать модуль потоковой передачи в многопоточности Python:

1. Импортируйте модуль потоковой передачи.

Создайте новый поток, импортировав модуль потоковой передачи, как показано.

Синтаксис:

 
import threading 

Модуль потоковой передачи состоит из класса Thread, который необходим для создания потока Python.

2. Объявление параметров потока: target функция, argument, and kwargs используются в качестве параметров класса Thread().

  • Target: определяет имя функции, выполняемой потоком.
  • Args: определяет аргументы, которые передаются имени целевой функции.

Пример:

 
import threading 
def print_hello(n): 
print("Hello, how old are you ", n) 
t1 = threading.Thread( target = print_hello, args =(18, )) 

В приведенном выше коде мы вызвали функцию print_hello() в качестве целевого параметра. Print_hello() содержит один параметр n, который передается в параметр args.

3. Запустите новый поток: чтобы запустить поток в многопоточности Python, вызовите объект класса потока. Метод start() может быть вызван один раз для каждого объекта потока; в противном случае возникает ошибка исключения.

Синтаксис:

 
t1.start() 
t2.start() 

4. Метод соединения: это метод join(), используемый в классе потока для остановки выполнения основного потока и ожидания полного выполнения объекта потока. Когда объект потока завершен, он запускает выполнение основного потока в Python.

Joinmethod.py

 
import threading 
def print_hello(n): 
 Print("Hello, how old are you? ", n) 
T1 = threading.Thread( target = print_hello, args =(20, )) 
T1.start() 
T1.join() 
Print("Thank you") 

Выход:

Hello, how old are you? 20 
Thank you 

Когда приведенная выше программа выполняется, метод join() останавливает выполнение основного потока и ждет, пока поток t1 не будет полностью выполнен. После успешного выполнения t1 основной поток начинает свое выполнение.

5. Синхронизация потоков в Python

Это механизм синхронизации потоков, который гарантирует, что никакие два потока не могут одновременно выполнять определенный сегмент внутри программы для доступа к общим ресурсам. Ситуацию можно назвать критическими участками. Мы используем состояние гонки, чтобы избежать состояния критического раздела, когда два потока не обращаются к ресурсам одновременно.

Напишем программу для использования модуля потоковой передачи в Python Multithreading.

Threading.py

 
import time # import time module 
import threading 
from threading import * 
def cal_sqre(num): # define a square calculating function 
    print(" Calculate the square root of the given number") 
    for n in num: # Use for loop  
        time.sleep(0.3) # at each iteration it waits for 0.3 time 
        print(' Square is : ', n * n) 
 
def cal_cube(num): # define a cube calculating function 
    print(" Calculate the cube of  the given number") 
    for n in num: # for loop 
        time.sleep(0.3) # at each iteration it waits for 0.3 time 
        print(" Cube is : ", n * n *n) 
 
ar =  # given array 
 
t = time.time() # get total time to execute the functions 
#cal_cube(ar) 
#cal_sqre(ar) 
th1 = threading.Thread(target=cal_sqre, args=(ar, )) 
th2 = threading.Thread(target=cal_cube, args=(ar, )) 
th1.start() 
th2.start() 
th1.join() 
th2.join() 
print(" Total time taking by threads is :", time.time() - t) # print the total time 
print(" Again executing the main thread") 
print(" Thread 1 and Thread 2 have finished their execution.") 

Выход:

Calculate the square root of the given number 
 Calculate the cube of the given number 
 Square is:  16 
 Cube is:  64 
 Square is:  25 
 Cube is:  125 
 Square is:  36 
 Cube is:  216 
 Square is:  49 
 Cube is:  343 
 Square is:  4 
 Cube is:  8 
 Total time taken by threads is: 1.5140972137451172 
 Again executing the main thread 
 Thread 1 and Thread 2 have finished their execution. 

Было полезно224
Нет28

1107-12cookie-checkМногопоточность и многопроцессорность в Python

Влияние GIL на многопоточные приложения

Если смотреть на типичную программу (не обязательно написанную на Python) — есть разница, ограничена ли эта программа производительностью процессора или же I/O.

Операции, ограниченные производительностью процессора (англ. CPU-bound) — это все вычислительные операции: перемножение матриц, поиск, обработка изображений и т. д.

Операции, ограниченные производительностью I/O (англ. I/O-bound) — это те операции, которые часто находятся в ожидании чего-либо от источников ввода/вывода (пользователь, файл, БД, сеть). Такие программы и операции иногда могут ждать долгое время, пока не получат от источника то, что им нужно. Это связано с тем, что источник может проводить собственные (внутренние) операции, прежде чем он будет готов выдать результат. Например, пользователь может думать над тем, что именно ввести в поисковую строку или же какой запрос отправить в БД.

Ниже приведена простая CPU-bound программа, которая попросту ведёт обратный отсчёт:

Запустив это на 4х-ядерном компьютере получим такой результат:

 - 6.20024037361145

Ниже приведена та же программа, с небольшим изменением. Теперь обратный отсчёт ведётся в двух параллельных потоках:

И вот результат:

 - 6.924342632293701 

Как видно из результатов, оба варианта затратили примерно одинаковое время. В многопоточной версии GIL предотвратил параллельное выполнение потоков.

GIL не сильно влияет на производительность I/O-операций в многопоточных программах, т. к. в процессе ожидания от I/O блокировка распространяется по потокам.

Однако программа, потоки которой будут работать исключительно с процессором (например обработка изображения по частям), из-за блокировки не только станет однопоточной, но и на её выполнение будет затрачиваться больше времени, чем если бы она изначально была строго однопоточной.

Такое увеличение времени — это результат появления и реализации блокировки.

global и nonlocal

global и nonlocal НЕ объявляет переменную, а определяет пространство имен переменной.
Позволяет изменять переменные за пределами текущей def.

Глобальные имена – это имена, которые определены на верхнем уровне вмещающего модуля.

  • читать такое имя можно и без global;
  • global нужно, чтобы присваивать глобальным именам.

Нелокальные имена — внешние для текущей def, но не верхний уровень модуля.

Здесь все переменные тоже глобальные:

Если x не существовала в момент вызова функции, то операция = создаст переменную х в области видимости модуля

Меньше глобальных переменных

Почему нужно стремиться делать меньше глобальных переменных?

Пусть мы хотим модифицировать этот модуль или использовать в другой программе. Чему равно х? Это зависит от того, какие функции вызывались. Сложнее понять код, ибо нужно знать как выполняется ВСЯ программа (кого вызывали последней — func1 или func2, или их вообще не вызывали).

В многопоточном программировании глобальные переменные используют в качестве общей памяти для разных потоков (т.е. средства связи между потоками).

Не изменяйте глобальные переменные непосредственно в других модулях

Пусть сначала написали модуль first.py, потом написали модуль second.py и далее пытаемся понять, как работает программа.
Изменение переменных модуля в другом модуле напрямую ухудщает читаемость кода.

Программист, поддерживающий first.py пытается найти кто его импортировал (и в какой директории) и изменил.

Меньше связей между модулями — проще поддерживать и изменять модули.

Лучше делать связи через вызовы функций и возвращаемые значения (проще контролировать).

nonlocal — «пропустить локальную область видимости при поиске имен»

Для чтения значений переменных не нужно. Только для =.

  • global
    • вынуждает интерпретатор начинать поиск имен с области объемлю-
      щего модуля;
    • позволяет присваивать переменным новые значения.
    • Область поиска простирается вплоть до встроенной области видимости, если
      искомое имя не будет найдено в модуле,
    • при этом операция присваивания значений глобальным именам всегда будет создавать или изменять переменные в области видимости модуля.
  • nonlocal
    • ограничивает область поиска областями видимости объемлющих функций;
    • требует, чтобы перечисленные в инструкции имена уже существовали,
    • позволяет присваивать им новые значения;
    • в область поиска не входят глобальная и встроенная области видимости.

По умолчанию нельзя изменять значения переменной объемлющей области видимости

unlocal — позволяет изменять, даже если функция tester завершила работу к моменту вызова функции nested через переменню F:

Напоминаем, каждый вызов фабричной фукнции tester будет создавать отдельную копию переменной state.
Объект state, находящийся в объемлющей области видимости, фактически прикрепляется к возвращаемому объекту функции nested — каждый вызов функции tester создает новый, независимый объект state, благодаря чему изменение state в одной функции не будет оказывать влияния на другие.
Вызываем еще эти же функции:

Что такое многопроцессорность в Python?

Многопроцессорность в Python – это способность системы запускать несколько процессов параллельно. Проще говоря, многопроцессорность использует два или более ЦП в одной компьютерной системе. Этот метод также может распределять задачи между процессами.

Блоки обработки совместно используют основную память и периферийные устройства для одновременной обработки программ. Многопроцессорное приложение разбивается на более мелкие части и работает независимо. Каждый процесс назначается процессору операционной системой.

Python предоставляет встроенный пакет, называемый multiprocessing, который поддерживает процессы подкачки. Прежде чем работать с многопроцессорной обработкой, мы должны ознакомиться с объектом процесса.

Синхронизация потоков

Если несколько потоков из общей модификации данных, может привести к возникновению непредсказуемых результатов, в целях обеспечения точности данных, необходимо синхронизировать несколько потоков.

объект резьбы с помощью замка и RLOCK может достигнуть простой синхронизации потоков, два объекта имеют методы получения и способы высвобождения, для тех, кто нуждается каждый из которых оставляет только одну нить рабочие данные, он может быть введен в эксплуатацию приобретать и освободить способы по номер. Как следует:

Многопоточность преимущество заключается в том, что он может одновременно выполнять несколько задач (по крайней мере, чувствует, как это). Но когда потоки должны обмениваться данными, не может быть никаких проблем синхронизации данных.

Рассмотрим случай: список всех элементов равны нулю, нить «набор» от задней стенки к передней всех элементов в одно целое, и нить «печать» спереди назад, отвечающий за чтение списка и печати.

Затем нить может быть «установить» начала меняться, когда «печать» нить это напечатать список, было бы половина выход половины 0, что данные не будут синхронизированы. Чтобы избежать такой ситуации, мы вводим понятие замка.

Замок имеет два состояния — заблокировать и разблокировать. Всякий раз, когда поток, такой как «набор» для доступа к общим данным, вы должны сначала получить блокировку, если у вас уже есть другой поток, например, как «печать», чтобы получить заперт, то пусть нить «набор» пауза, которая является синхронным блокирование; дожидаемся нити » печать «доступ завершается, после выхода замка, пусть нить» набор «, чтобы продолжить.

После такого процесса, при печати списка всех выходе 0 или 1 полную мощность, больше не появляется половину дозы смущения 0 1 половину.

Пример:

#!/usr/bin/python3

import threading
import time

class myThread (threading.Thread):
    def __init__(self, threadID, name, counter):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.counter = counter
    def run(self):
        print ("开启线程: " + self.name)
        # 获取锁,用于线程同步
        threadLock.acquire()
        print_time(self.name, self.counter, 3)
        # 释放锁,开启下一个线程
        threadLock.release()

def print_time(threadName, delay, counter):
    while counter:
        time.sleep(delay)
        print ("%s: %s" % (threadName, time.ctime(time.time())))
        counter -= 1

threadLock = threading.Lock()
threads = []

# 创建新线程
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)

# 开启新线程
thread1.start()
thread2.start()

# 添加线程到线程列表
threads.append(thread1)
threads.append(thread2)

# 等待所有线程完成
for t in threads:
    t.join()
print ("退出主线程")

Вышеприведенная программа, выход:

开启线程: Thread-1
开启线程: Thread-2
Thread-1: Wed Apr  6 11:52:57 2016
Thread-1: Wed Apr  6 11:52:58 2016
Thread-1: Wed Apr  6 11:52:59 2016
Thread-2: Wed Apr  6 11:53:01 2016
Thread-2: Wed Apr  6 11:53:03 2016
Thread-2: Wed Apr  6 11:53:05 2016
退出主线程

5.1.4. Анонимные функции¶

Python поддерживает синтаксис, позволяющий определять анонимные функции (лямбда-функции или лямбда-выражения):

lambda
lambda parameters expression
  • часть является необязательной, и если она присутствует, то обычно представляет собой простой список имен переменных, разделенных запятыми (позиционных аргументов);

  • выражение не может содержать условных инструкций или циклов (условные выражения — допустимы), а также не может содержать инструкцию ;

  • результатом лямбда-выражения является анонимная функция.

Когда лямбда-функция вызывается, она возвращает результат вычисления выражения .

Пример записи лямбда-функции приведен в Листинге 5.1.15.

Зачем нужна многопроцессорность?

Многопроцессорность необходима для выполнения множества задач в компьютерной системе. Предположим, компьютер не многопроцессорный, а однопроцессорного типа. Мы назначаем этой системе различные процессы одновременно.

Ему придется прервать предыдущую задачу и перейти к другой, чтобы все процессы продолжались. Принцип схож с тем, как повар работает один на кухне. Чтобы приготовить еду, он должен выполнять несколько задач, таких как нарезка, очистка, приготовление пищи, замешивание теста, выпечка и т. д.

Следовательно, многопроцессорность необходима для выполнения нескольких задач одновременно без прерывания. Это также позволяет легко отслеживать все задачи. Вот почему важна необходимость концепции многопроцессорности:

  • Многопроцессорность можно представить как компьютер с более чем одним центральным процессором.
  • Многоядерный процессор относится к одному вычислительному компоненту с двумя или более независимыми блоками.

В многопроцессорном режиме ЦП может назначать несколько задач, каждая из которых имеет свой собственный процессор.

Работа с базовыми функциями

Разберём, как устроены базовые функции в Python.

Чтобы записать в переменную V сумму 1 и 1, мы напишем так:

Если мы захотим напечатать переменную V, мы используем функцию:

Напоминаем, что в Python мы не пишем тип переменных.

При спуске этот код выведет нам 2.

Если вы забыли, что делает функция, или нашли новую, вам поможет команда help (): она выпишет основную информацию о функции. Если мы используем ее на функцию print (), это будет выглядеть так:

В программировании мы будем много работать с числами. Все основные математические операции записываются в Python привычным образом, примерно как в калькуляторе:

Есть и операции поинтереснее, менее очевидные:

Иногда в Python можно встретить артефакты вроде такого:

В конце получившегося числа мы неожиданно видим 4. Это просто особенность компьютерного представления данных, и бояться этого не стоит, в большинстве случаев это не имеет значения. Но не забывайте об этой особенности, если вам важны точные числа (как, например, в астрофизике).

Вывод текста. Уже сложилась традиция, что первые слова, которые человек выписывает кодом, это «Hello, World!». Сделаем это и мы.

Мы уже выводили выше переменную, теперь выведем текст. Сделать это в Python очень просто:

Иногда (например, в цикле) надо выводить одно и то же с небольшим изменением. Для этого используется форматированный вывод. Это делается так: заменим часть, которая будет меняться, фигурными скобками, а за фразой напишем .format (). В скобки вставим переменную с нужным значением. Вот как это выглядит:

В некоторых версиях Python можно сделать то же самое и другим способом:

Результат будет один и тот же. Если у вас работают обе версии, то делайте так, как вам больше нравится.

Как устроены операции сравнения в Python

  1. Операции сравнения будут возвращать ответ в виде правда/неправда: True/False.
  2. Для проверки на равенство используются два знака «равно».
  3. Для проверки на неравенство используется восклицательный знак (знак отрицания) со знаком «равно».

Например:

Обратный вызов (callback)

Пример. Обращение к трем URL-адресам одновременно с использованием библиотеки Tornado.

import tornado.ioloop

from tornado.httpclient import AsyncHTTPClient

urls = ['http://www.google.com', 'http://www.yandex.ru', 'http://www.python.org']

def handle_response(response):

    if response.error:

        print("Error:", response.error)

    else:

        url = response.request.url

        data = response.body

        print('{}: {} bytes: {}'.format(url, len(data), data))

http_client = AsyncHTTPClient()

for url in urls:

    http_client.fetch(url, handle_response)

    

tornado.ioloop.IOLoop.instance().start()

где:

  • handle_response — обратный вызов;
  • print(“Error:”, response.error) — строка проверяет ошибки. Это необходимо, потому что из-за цикла событий код не может обрабатывать исключения. Любые исключения, которые могут быть созданы в функции обратного вызова, являются причиной остановки программы и цикла событий. Именно поэтому они передаются в виде объектов. Если данная строка не будет проверять ошибки, они не будут обрабатываться вообще.

Благодаря используемому в коде методу AsyncHTTPClient.fetch информацию об URL-адресе можно получать без блокировки. Каждая последующая строка выполняется еще до того, как получен ответ по URL, а значит, результат выполнения получить невозможно. fetch возвращает объект, вызывая функцию обратного вызова — handle_response.

Обратный вызов в асинхронном программировании, пожалуй, единственный способ избежать блокировки. Именно по этой причине может возникать длинная цепочка действий, состоящая из функций обратного вызова, безостановочно сменяющих одна другую. Каждый обратный вызов — это отдельный поток, и он не всегда может принять все объекты, особенно если используются сторонние API-интерфейсы.

Conclusion: Threading in Python

You’ve now seen much of what Python has to offer and some examples of how to build threaded programs and the problems they solve. You’ve also seen a few instances of the problems that arise when writing and debugging threaded programs.

If you’d like to explore other options for concurrency in Python, check out Speed Up Your Python Program With Concurrency.

If you’re interested in doing a deep dive on the module, go read Async IO in Python: A Complete Walkthrough.

Whatever you do, you now have the information and confidence you need to write programs using Python threading!

Special thanks to reader JL Diaz for helping to clean up the introduction.

Добавляем потоки в таймер

Первое, что нам нужно сделать, — вынести код таймера-напоминания в отдельную функцию, чтобы создать с ней поток. Для этого используем команду :

Теперь сделаем новый поток, в который отправим выполняться нашу новую функцию. Так как аргументов у нас нет, то и аргументы передавать не будем, а напишем args=().

Нам осталось убедиться в том, что пока поток работает, мы можем выполнять в программе что-то ещё и наше засыпание в потоке на это не повлияет. Для этого мы через 20 секунд после запуска выведем сообщение на экран. За 20 секунд пользователь успеет ввести напоминание и время, после чего таймер уйдёт в новый поток и там уснёт на нужное количество минут. Но это не помешает работе основной программы — она тоже будет выполнять свои команды параллельно с потоком.

Результат:

Импортируйте модуль потоковой передачи.

Для создания потока мы будем использовать модуль .

import threading

Модуль передачи состоит из класса который создается для создания потока.

Поток может быть создан путем создания объекта класса Thread. Аргументы для этого класса следующие:

  1. target: здесь указывается функция, которая будет вызываться потоком. Эта функция представляет собой вызываемый объект, вызываемый методом потока.
  2. args: Здесь мы указываем аргументы функции.
def print_hi(num): 
    print("Hi, you are customer ",num)

t1 = threading.Thread(target=print_square, args=(10,))

Приведенный выше фрагмент кода вызывает вызываемую как параметр. У этой функции есть один параметр, а именно который указывается с помощью .

Начало работы в Питоне

Первое, что делают при изучении любого языка программирования, – вывод в консоль популярного сообщения «Hello world». Немного поменяем вывод, и в пустом файле скрипта напишем следующую команду:

Print – встроенная в Python функция, которая выводит на печать переданное в нее сообщение. Запуск скрипта отобразит в терминале соответствующую фразу.

Еще одна полезная команда – input. Она позволяет как бы общаться с пользователем при помощи консоли. Исполним следующий код:

Функция input приостанавливает исполнение скрипта до тех пор, пока пользователь не введет свой ответ. Сначала в консоли потребуется представиться, а потом передать свой возраст. И лишь потом в терминале отобразится сообщение: «Рад знакомству!».

Пока что все наши операции не имели большого смысла и никак не использовались в других местах программы, но легкость Питона, уважаемые читатели, наверняка ощущается.

Обсудим базовый синтаксис языка Python:

  1. Любая часть кода отделяется от предыдущей переводом на новую строку (не нужно никаких точек с запятой в конце);
  2. Отступы внутри блоков кода (о них пойдет речь дальше) задаются 4-мя пробелами;
  3. Создаваемые функции и объекты отделяются друг от друга двумя пустыми строчками.

Даже если вы и забудете о сказанном, PyCharm вам напомнит: он подчеркнет синтаксические ошибки, даст подсказки по используемым функциям. Это не просто удобно, но и экономит массу времени.

Данная фраза от создателя языка свидетельствует о том, что Питон в своем синтаксисе максимально прозрачен.

Семафоры

Семафоры (их иногда называют семафорами Дийкстры (Dijkstra) по имени их изобретателя) являются более общим механизмом синхронизации потоков, нежели замки. Семафоры могут допустить в критическую область программы сразу несколько потоков. Семафор имеет счетчик запросов, уменьшающийся с каждым вызовом метода acquire() и увеличивающийся при каждом вызове release(). Счетчик не может стать меньше нуля, поэтому в таком состоянии потокам приходится ждать, как и в случае с замками, пока значение счетчика не увеличится.

Конструктор класса threading.Semaphore принимает в качестве (необязательного) аргумента начальное состояние счетчика (по умолчанию оно равно 1, что соответствует замку класса Lock ). Методы acquire() и release() действуют аналогично описанным выше одноименным методам у замков.

Семафор может применяться для охраны ограниченного ресурса. Например, с его помощью можно вести пул соединений с базой данных. Пример такого использования семафора (заимствован из документации к Python) дан ниже:

from threading import BoundedSemaphore
           maxconnections = 5
           # Подготовка семафора
           pool_sema = BoundedSemaphore(value=maxconnections)
           # Внутри потока:
           pool_sema.acquire()
           conn = connectdb()
           # ... использование соединения ...
           conn.close()
           pool_sema.release()

Таким образом, применяется не более пяти соединений с базой данных. В примере использован класс threading.BoundedSemaphore. Экземпляры этого класса отличаются от экземпляров класса threading.Semaphore тем, что не дают сделать release() больше, чем сделан acquire().

Списки, кортежи, множества и словари

Списки, кортежи, множества и словари – еще 4 типа данных в Питоне, включающие в себя несколько значений и являющиеся итерируемыми (перебираемыми, как строки).

Особенности показаны в таблице 3.

Список (list) Кортеж (tuple) Множество (set) Словарь (dict)
Изменяемый Неизменяемый Изменяемое Изменяемый
Значения могут дублироваться Значения могут дублироваться Значения не могут дублироваться Ключи не могут дублироваться
Доступ по индексу возможен Доступ по индексу возможен Доступ по индексу невозможен Есть доступ к ключам и значениям

Таблица 3 – Коллекции данных в Python

Список – последовательность произвольных элементов, разделенных запятой. Обозначается квадратными скобками. Можно доставать отдельные составляющие через индекс, добавить в начало списка или конец те или иные значения, удалить элементы, узнать длину, отсортировать.

Рассмотрим часть функционала.

Результат работы скрипта:

Когда необходимо запретить изменение коллекции, ее удобно представлять в виде кортежа. Более того, он занимает меньшее количество в памяти. Записывается в круглых скобках.

На их основании также возможны срезы, доступ по индексу, нахождение максимума или минимума (если элементы представлены числами), поиск количества вхождений значений.

Результат работы скрипта:

Множества хороши в ситуациях, когда нужна гарантия уникальности всех элементов. Задаются фигурными скобками. При добавлении дубликата размер сета никак не меняется

Важно и то, что порядок объектов внутри множества не гарантирован, что исключает доступ по индексу

Результат работы скрипта:

Словарь – особый тип коллекций. Все его элементы состоят из пар «ключ: значение». Ключ должен быть уникальным, а значения могут повторяться. Обозначается фигурными скобками.

Рассмотрим некоторые операции со словарями.

Результат работы скрипта:

Таким образом, в зависимости от ситуации применяется тот или иной тип коллекций. Чаще всего это списки и словари.

Python thread creating using class

Here, we can see how to create thread using class in python.

Syntax to create thread class:

To create a thread using class in python there are some class methods:

  • run() – This method calls the target function that is passed to the object constructor.
  • start() – Thread activity is started by calling the start()method, when we call start() It internally invokes the run method and executes the target object.
  • join() – This method blocks calling thread until the thread whose join() is called terminates normally or through handle exception.
  • getName() – This method returns a name for the thread.
  • setName(name) – This method is used to set the thread name, the name in the form of a string, and is used for identification.
  • isAlive() – This method returns that the thread is alive or not. The thread is alive at the time when the start() is invoked and lasts until the run() terminates.
  • setDaemon(Daemonic) – This method is used to set the daemon flag to Boolean value daemonic. this should be called before the start().
  • isDaemon() – This method returns the value of the thread’s daemon flag.
  • In this example, I have imported a module called thread from threading and defined a function as a threaded function and an argument is passed.
  • The value of __name__ attribute is set to “__main__”. When the module is run as a program. __name__ is the inbuilt variable that determines the name for a current module.
  • If the module is running directly from the command line then “__name__” is set to “__main__”.

Example:

You can see in the below screenshot that python guides printed three times as mentioned in the range().


Python thread creating using class

Пример многопроцессорной обработки

Предположим, у нас есть несколько задач. Итак, мы создаем две очереди: первая очередь будет обслуживать задачи, а другая будет хранить полный журнал задач. Следующим шагом является создание экземпляров процессов для выполнения задачи. Как обсуждалось ранее, класс Queue уже синхронизирован, поэтому нам не нужно получать блокировку с помощью класса Lock.

Мы объединим все классы многопроцессорной обработки вместе. Давайте посмотрим на пример ниже.

Пример –

from multiprocessing import Lock, Process, Queue, current_process  
import time  
import queue   
  
  
def jobTodo(tasks_to_perform, complete_tasks):  
    while True:  
        try:  
  
            # The try block to catch task from the queue.  
            # The get_nowait() function is used to  
            # raise queue.Empty exception if the queue is empty.  
  
            task = tasks_to_perform.get_nowait()  
  
        except queue.Empty:  
  
            break  
        else:  
  
                # if no exception has been raised, the else block will execute  
                # add the task completion  
                  
  
            print(task)  
            complete_tasks.put(task + ' is done by ' + current_process().name)  
            time.sleep(.5)  
    return True  
  
  
def main():  
    total_task = 8  
    total_number_of_processes = 3  
    tasks_to_perform = Queue()  
    complete_tasks = Queue()  
    number_of_processes = []  
  
    for i in range(total_task):  
        tasks_to_perform.put("Task no " + str(i))  
  
    # defining number of processes  
    for w in range(total_number_of_processes):  
        p = Process(target=jobTodo, args=(tasks_to_perform, complete_tasks))  
        number_of_processes.append(p)  
        p.start()  
  
    # completing process  
    for p in number_of_processes:  
        p.join()  
  
    # print the output  
    while not complete_tasks.empty():  
        print(complete_tasks.get())  
  
    return True  
  
  
if __name__ == '__main__':  
    main()

Выход:

Task no 2 
Task no 5 
Task no 0 
Task no 3 
Task no 6 
Task no 1 
Task no 4 
Task no 7 
Task no 0 is done by Process-1 
Task no 1 is done by Process-3 
Task no 2 is done by Process-2 
Task no 3 is done by Process-1 
Task no 4 is done by Process-3 
Task no 5 is done by Process-2 
Task no 6 is done by Process-1 
Task no 7 is done by Process-3 
Рейтинг
( Пока оценок нет )
Editor
Editor/ автор статьи

Давно интересуюсь темой. Мне нравится писать о том, в чём разбираюсь.

Понравилась статья? Поделиться с друзьями:
Люкс-хост
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: