🕷️ Crawler Inspector

URL Lookup

Direct Parameter Lookup

Raw Queries and Responses

1. Shard Calculation

Query:
Response:
Calculated Shard: 151 (from laksa036)

2. Crawled Status Check

Query:
Response:

3. Robots.txt Check

Query:
Response:

4. Spam/Ban Check

Query:
Response:

5. Seen Status Check

ℹ️ Skipped - page is already crawled

📄
INDEXABLE
CRAWLED
12 days ago
🤖
ROBOTS ALLOWED

Page Info Filters

FilterStatusConditionDetails
HTTP statusPASSdownload_http_code = 200HTTP 200
Age cutoffPASSdownload_stamp > now() - 6 MONTH0.4 months ago
History dropPASSisNull(history_drop_reason)No drop reason
Spam/banPASSfh_dont_index != 1 AND ml_spam_score = 0ml_spam_score=0
CanonicalPASSmeta_canonical IS NULL OR = '' OR = src_unparsedNot set

Page Details

PropertyValue
URLhttp://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html
Last Crawled2026-03-30 00:51:48 (12 days ago)
First Indexed2025-05-25 10:55:46 (10 months ago)
HTTP Status Code200
Meta Titlemultiprocessing — Процессный параллелизм — Документация Python 3.8.8
Meta Descriptionnull
Meta Canonicalnull
Boilerpipe Text
Введение ¶ multiprocessing - это пакет, который поддерживает порождение процессов с использованием API, похожим на модуль threading . Пакет multiprocessing предлагает как локальный, так и удаленный параллелизм, эффективно обходя Глобальную блокировку интерпретатора с использованием подпроцессов вместо потоков. Также модуль multiprocessing позволяет программисту полностью использовать несколько процессоров на данном компьютере. Работает как на Unix, так и на Windows. Модуль multiprocessing также вводит API, которые не имеет аналогов в модуле threading . Ярким примером этого является объект Pool , который предлагает удобное средство параллелирования выполнения функции по множеству входных значениц, распределения входных данных по процессам (параллелизм данных). Следующий пример демонстрирует обычную практику определения таких функций в модуле, чтобы дочерние процессы могли успешно импортировать этот модуль. Этот базовый пример параллелизма данных с использованием Pool : from multiprocessing import Pool def f ( x ): return x * x if __name__ == '__main__' : with Pool ( 5 ) as p : print ( p . map ( f , [ 1 , 2 , 3 ])) будет напечатано в стандартный вывод: [ 1 , 4 , 9 ] Класс Process ¶ В multiprocessing процессы порождаются созданием объекта Process , а затем вызовом его метода start() . Process следует API threading.Thread . Тривиальный пример многопроцессорной программы: from multiprocessing import Process def f ( name ): print ( 'hello' , name ) if __name__ == '__main__' : p = Process ( target = f , args = ( 'bob' ,)) p . start () p . join () Ниже приведен развернутый пример, показывающий соответствующие идентификаторы отдельных процессов: from multiprocessing import Process import os def info ( title ): print ( title ) print ( 'module name:' , __name__ ) print ( 'parent process:' , os . getppid ()) print ( 'process id:' , os . getpid ()) def f ( name ): info ( 'function f' ) print ( 'hello' , name ) if __name__ == '__main__' : info ( 'main line' ) p = Process ( target = f , args = ( 'bob' ,)) p . start () p . join () Объяснение причины необходимости if __name__ == '__main__' части см. в разделе Программирование рекомендаций . Контексты и методы запуска ¶ В зависимости от платформы, multiprocessing поддерживает три способа запуска процесса. Далее перечислены методы запуска . spawn Родительский процесс запускает новый процесс интерпретатора Python. Дочерний процесс унаследует только те ресурсы, которые необходимы для выполнения метода run() объекта процесса. В частности, ненужные файловые дескрипторы и дескрипторы родительского процесса не будут унаследованы. Запуск процесса с использованием этого метода довольно медленный по сравнению с использованием fork или forkserver . Доступно в Unix и Windows. Значение по умолчанию для Windows и macOS. fork Родительский процесс использует os.fork() для форсирования Python интерпретатор. Дочерний процесс, когда он начинается, фактически идентичен родительскому процессу. Все ресурсы родителя наследуются дочерним процессом. Следует отметить, что безопасная форсировка многопоточного процесса является проблематичной. Доступно только в Unix. Значение по умолчанию в Unix. forkserver Когда программа начинает и выбирает метод начала forkserver , процесс сервера, начат. С этого момента всякий раз, когда требуется новый процесс, родительский процесс подключается к серверу и запрашивает, чтобы он форсировал новый процесс. Процесс сервера вилки является однопотоковым, поэтому он безопасен для использования os.fork() . Ненужные ресурсы не наследуются. Доступный на платформах Unix, которые поддерживают мимолетный файл дескрипторы по Unix пайпы. Изменено в версии 3.8: На macOS метод начала spawn - теперь дефолт. Метод запуска fork следует считать небезопасным, поскольку он может привести к сбоям подпроцессы. См. bpo-33725 . Изменено в версии 3.4: spawn добавлены на всех платформах unix и forkserver добавлены для некоторых платформ unix. Дочерние процессы больше не наследуют все унаследованные родительские дескрипторы в Windows. В Unix с помощью методов запуска spawn или forkserver также запускается процесс resource tracker , который отслеживает несвязанные именованные системные ресурсы (такие как именованные семафоры или SharedMemory объекты), созданные процессами программы. После завершения всех процессов средство отслеживания ресурсов отменяет связь с любым оставшимся отслеживаемым объектом. Обычно их не должно быть, но если какой-либо процесс был убит сигналом, то может возникнуть некоторая «утечка» ресурсов. (Ни просочившиеся семафоры, ни сегменты общей памяти не будут автоматически отключены до следующей перезагрузки. Это проблематично для обоих объектов, поскольку система допускает только ограниченное количество именованных семафоров, а сегменты совместно используемой памяти занимают некоторое место в основной памяти.) Для выбора метода запуска используется set_start_method() в if __name__ == '__main__' клаузула основного модуля. Например: import multiprocessing as mp def foo ( q ): q . put ( 'hello' ) if __name__ == '__main__' : mp . set_start_method ( 'spawn' ) q = mp . Queue () p = mp . Process ( target = foo , args = ( q ,)) p . start () print ( q . get ()) p . join () set_start_method() не должны быть используемый более одного раза в программе. Кроме того, можно использовать get_context() для получения объекта контекст. Объекты контекста имеют тот же API, что и модуль многопроцессорной обработки, и позволяют использовать несколько методов запуска в одной программе: import multiprocessing as mp def foo ( q ): q . put ( 'hello' ) if __name__ == '__main__' : ctx = mp . get_context ( 'spawn' ) q = ctx . Queue () p = ctx . Process ( target = foo , args = ( q ,)) p . start () print ( q . get ()) p . join () Обратите внимание, что объекты, связанные с одним контекст, могут быть несовместимы с процессами для другого контекст. В частности, блокировки, созданные с помощью fork контекст, не могут быть переданы процессам, запущенным с помощью методов запуска spawn или forkserver . Библиотека, которая хочет использовать конкретный метод запуска, должна, вероятно, использовать get_context() , чтобы избежать вмешательства в выбор пользователя библиотеки. Предупреждение Стартовые методы 'spawn' и 'forkserver' в настоящее время не могут быть используемый с «замороженными» исполняемыми файлами (т.е. двоичными файлами, создаваемыми пакетами, такими как PyInstaller and cx_Freeze ) в Unix. Стартовый метод 'fork' работает. Обмен объектами между процессами ¶ multiprocessing поддерживает два типа каналов связи между процессами: Очереди Класс Queue является близким клоном queue.Queue . Например: from multiprocessing import Process , Queue def f ( q ): q . put ([ 42 , None , 'hello' ]) if __name__ == '__main__' : q = Queue () p = Process ( target = f , args = ( q ,)) p . start () print ( q . get ()) # распечатает "[42, None, 'hello']" p . join () Очереди поток и безопасны для обработки. Пайпы Pipe() функционируют возвращает пара объектов связи, связанных пайп, который по умолчанию является (двухсторонним) дуплексом. Например: from multiprocessing import Process , Pipe def f ( conn ): conn . send ([ 42 , None , 'hello' ]) conn . close () if __name__ == '__main__' : parent_conn , child_conn = Pipe () p = Process ( target = f , args = ( child_conn ,)) p . start () print ( parent_conn . recv ()) # распечатает "[42, None, 'hello']" p . join () Два объекта соединения возвращенный Pipe() представляют два конца пайп. Каждый объект подключения имеет методы send() и recv() (среди прочих). Обратите внимание, что данные в пайп могут быть повреждены, если два процесса (или потоки) пытаются одновременно считать или записывать в same конец пайп. Конечно, нет риска коррупции от процессов, использующих разные концы пайп одновременно. Синхронизация между процессами ¶ multiprocessing содержит эквиваленты всех примитивов синхронизации из threading . Для сущность можно использовать блокировку для обеспечения одновременной печати только одного процесса в стандартный вывод: from multiprocessing import Process , Lock def f ( l , i ): l . acquire () try : print ( 'hello world' , i ) finally : l . release () if __name__ == '__main__' : lock = Lock () for num in range ( 10 ): Process ( target = f , args = ( lock , num )) . start () Без использования блокировки выходные данные различных процессов могут быть смешаны. Совместное использование состояние между процессами ¶ Как упомянуто выше, когда выполнение параллельного программирования его является обычно лучшим избегать использования разделенного состояние в максимально возможной степени. Это особенно верно при использовании нескольких процессов. Однако, если вам действительно нужно использовать некоторые общие данные, то multiprocessing предоставляет пару способов сделать это. Общая память Данные могут храниться в карте совместно используемой памяти с помощью Value или Array . Например, следующие код: from multiprocessing import Process , Value , Array def f ( n , a ): n . value = 3.1415927 for i in range ( len ( a )): a [ i ] = - a [ i ] if __name__ == '__main__' : num = Value ( 'd' , 0.0 ) arr = Array ( 'i' , range ( 10 )) p = Process ( target = f , args = ( num , arr )) p . start () p . join () print ( num . value ) print ( arr [:]) напечатает: 3.1415927 [ 0 , - 1 , - 2 , - 3 , - 4 , - 5 , - 6 , - 7 , - 8 , - 9 ] Аргументы 'd' и 'i' используемый при создании num и arr являются типкодами вида используемый модулем array : 'd' указывает двойную точность float и 'i' обозначает целое число со знаком. Эти общие объекты будут процессом и потокобезопасной. Для большей гибкости в использовании совместно используемой памяти можно использовать модуль multiprocessing.sharedctypes , поддерживающий создание объектов произвольных ctypes, выделенных из совместно используемой памяти. Серверный процесс Объект менеджера возвращенный Manager() управляет серверным процессом, который содержит объекты Python и позволяет другим процессам манипулировать ими с помощью прокси. Менеджер возвращенный Manager() поддержит типы list , dict , Namespace , Lock , RLock , Semaphore , BoundedSemaphore , Condition , Event , Barrier , Queue , Value и Array . Например,: from multiprocessing import Process , Manager def f ( d , l ): d [ 1 ] = '1' d [ '2' ] = 2 d [ 0.25 ] = None l . reverse () if __name__ == '__main__' : with Manager () as manager : d = manager . dict () l = manager . list ( range ( 10 )) p = Process ( target = f , args = ( d , l )) p . start () p . join () print ( d ) print ( l ) напечатает: { 0.25 : None , 1 : '1' , '2' : 2 } [ 9 , 8 , 7 , 6 , 5 , 4 , 3 , 2 , 1 , 0 ] Менеджеры серверных процессов более гибки, чем использование общих объектов памяти, поскольку они могут быть созданы для поддержки произвольных типов объектов. Кроме того, один менеджер может совместно использоваться процессами на разных компьютерах по сети. Однако они работают медленнее, чем совместно используемая память. Использование пула воркеров ¶ Класс Pool представляет пул рабочих процессов. Он содержит методы, позволяющие выгружать задачи в рабочие процессы несколькими различными способами. Например: from multiprocessing import Pool , TimeoutError import time import os def f ( x ): return x * x if __name__ == '__main__' : # запуск 4 рабочих процессов with Pool ( processes = 4 ) as pool : # печать "[0, 1, 4,..., 81]" print ( pool . map ( f , range ( 10 ))) # печатать одинаковые числа в произвольном порядке for i in pool . imap_unordered ( f , range ( 10 )): print ( i ) # вычислить "f(20)" асинхронно res = pool . apply_async ( f , ( 20 ,)) # запускается в *только* одном процессе print ( res . get ( timeout = 1 )) # печатает "400" # вычислить "os.getpid()" асинхронно res = pool . apply_async ( os . getpid , ()) # запускается в *только* одном процессе print ( res . get ( timeout = 1 )) # печатает PID этого процесса # запуск нескольких оценок асинхронно *может* использовать больше процессов multiple_results = [ pool . apply_async ( os . getpid , ()) for i in range ( 4 )] print ([ res . get ( timeout = 1 ) for res in multiple_results ]) # уснуть одному рабочему на 10 секунд res = pool . apply_async ( time . sleep , ( 10 ,)) try : print ( res . get ( timeout = 1 )) except TimeoutError : print ( "We lacked patience and got a multiprocessing.TimeoutError" ) print ( "For the moment, the pool remains available for more work" ) # выход из блока with с остановкой пула print ( "Now the pool is closed and no longer available" ) Обратите внимание, что методы бассейна должны только когда-либо быть используемый процессом, который создал его. Примечание Функциональность этого пакета требует, чтобы модуль __main__ был импортирован нижестоящими элементами. Это освещено в Программирование рекомендаций , однако здесь стоит указать. Это означает, что некоторые примеры, такие как примеры multiprocessing.pool.Pool не будут работать в интерактивном интерпретатор. Например: >>> >>> from multiprocessing import Pool >>> p = Pool ( 5 ) >>> def f ( x ): ... return x * x ... >>> with p : ... p . map ( f , [ 1 , 2 , 3 ]) Process PoolWorker-1: Process PoolWorker-2: Process PoolWorker-3: Traceback (most recent call last): AttributeError : 'module' object has no attribute 'f' AttributeError: 'module' object has no attribute 'f' AttributeError: 'module' object has no attribute 'f' (Если попробовать это, то на самом деле будет выведено три полных трейсбэки, перемежающихся полуслучайным образом, а затем, возможно, придется как-то остановить родительский процесс. Ссылка ¶ Пакет multiprocessing в основном реплицирует API модуля threading . Process и исключения ¶ class multiprocessing. Process ( group=None , target=None , name=None , args=() , kwargs={} , * , daemon=None ) ¶ Объекты процесса представляют собой операцию, выполняемую в отдельном процессе. Класс Process имеет эквиваленты всех методов threading.Thread . Конструктор всегда должен вызываться с аргументами ключевой. group всегда должны быть None ; он существует исключительно для совместимости с threading.Thread . target - вызываемый объект, вызываемый методом run() . По умолчанию он имеет значение None , то есть ничего не называется. name - имя процесса (более подробную информацию см. в разделе name ). args - кортеж аргументов для целевого вызова. kwargs - словарь ключевой аргументов для целевого вызова. Если указано, только ключевой аргумент daemon задает для флага процесса daemon значение True или False . Если значение равно None (по умолчанию), этот флаг наследуется от процесса создания. По умолчанию аргументы не передаются target . Если подкласс отвергает конструктора, он должен удостовериться, что призывает конструктора базового класса ( Process.__init__() ) прежде, чем сделать что-либо еще к процессу. Изменено в версии 3.3: Добавлен аргумент daemon . run ( ) ¶ Метод, представляющий активность процесса. Этот метод можно переопределить в подкласс. Стандартный метод run() призывает подлежащий выкупу объект, переданный конструктору объекта как целевой аргумент, если таковые имеются, с последовательными и аргументами ключевой, взятыми от args и аргументов kwargs , соответственно. start ( ) ¶ Запустите действие процесса. Это должно вызываться не более одного раза для каждого объекта процесса. Она обеспечивает возможность вызова метода run() объекта в отдельном процессе. join ( [ timeout ] ) ¶ Если необязательным аргументом timeout является None (по умолчанию), метод блокируется до завершения процесса, метод join() которого вызывается. Если timeout - положительное число, оно блокируется максимум через timeout секунд. Обратите внимание, что метод возвращает None , если его процесс завершается или время ожидания метода истекло. Проверьте exitcode процесса, чтобы определить его завершение. Процесс может быть объединен много раз. Процесс не может присоединиться к самому себе, поскольку это приведет к взаимоблокировке. Ошибка при попытке присоединения к процессу перед его запуском. name ¶ Имя процесса. Имя - строка используемый в идентификационных целях только. У него нет семантики. Нескольким процессам может быть присвоено одно и то же имя. Начальное имя задается конструктором. Если для конструктора не указано явное имя, создается имя формы „Process-N:sub: 1 : N:sub: 2 :…: N:sub: k “, где каждый N k является N-м потомком своего родителя. is_alive ( ) ¶ Возвращает жив ли процесс. Примерно, объект процесса жив с момента возвращает метода start() до завершения дочернего процесса. daemon ¶ Флаг демона процесса, логический значение. Это должно быть установлено, прежде чем start() называют. Начальный значение унаследован от процесса создания. Когда процесс завершается, он пытается завершить все свои демонические дочерние процессы. Обратите внимание, что демоническому процессу запрещено создавать дочерние процессы. В противном случае демонический процесс оставит своих потомков сиротами, если он завершится после завершения родительского процесса. Кроме того, это демоны или службы не Unix, это обычные процессы, которые будут прекращены (и не присоединены), если не демонические процессы вышли. В дополнение к threading.Thread API объекты Process также поддерживают следующий атрибуты и methods: pid ¶ Возвращает идентификатор процесса. Перед началом процесса это будет None . exitcode ¶ Выход ребенка код. Это будет None , если процесс еще не завершен. Отрицательный значение -N указывает на то, что дочерний объект был завершен сигналом N . authkey ¶ Ключ аутентификации процесса (байтовая строка). Когда multiprocessing инициализируется, основному процессу присваивается случайный строка с помощью os.urandom() . При создании объекта Process он наследует ключ аутентификации родительского процесса, хотя его можно изменить, установив для параметра authkey значение другого байта строка. См. Ключи аутентификации . sentinel ¶ Числовой дескриптор системного объекта, который становится «готовым» по завершении процесса. Вы можете использовать этот значение, если вы хотите ждать на нескольких событиях, сразу используя multiprocessing.connection.wait() . В противном случае вызов join() проще. В Windows это дескриптор ОС, используемый с семейством вызовов API WaitForSingleObject и WaitForMultipleObjects . На Unix это - файл дескриптор, применимый с примитивами от модуля select . Добавлено в версии 3.3. terminate ( ) ¶ Завершить процесс. В Unix это выполняется с помощью сигнала SIGTERM ; на Windows используется TerminateProcess() . Следует отметить, что обработчики exit и finally и т.д. выполняться не будут. Заметим, что потомки процесса не будут прекращены - они просто осиротеют. Предупреждение Если этот метод является используемый, когда связанный процесс использует пайп или очередь, то пайп или очередь может быть повреждена и может стать непригодной для использования другим процессом. Аналогично, если процесс приобрел блокировку или семафор и т.д., то завершение его может привести к взаимоблокировке других процессов. kill ( ) ¶ То же, что и terminate() , но с использованием сигнала SIGKILL в Unix. Добавлено в версии 3.7. close ( ) ¶ Закрыть объект Process , освободив все связанные с ним ресурсы. ValueError возникает, если базовый процесс все еще выполняется. Как только close() возвращает успешно, большинство других методов и атрибуты объекта Process поднимут ValueError . Добавлено в версии 3.7. Обратите внимание, что start() , join() , is_alive() , terminate() и методы exitcode должен только вызвать процесс, который создал объект процесса. Пример использования некоторых методов Process : >>> import multiprocessing, time, signal >>> p = multiprocessing.Process(target=time.sleep, args=(1000,)) >>> print(p, p.is_alive()) <Process ... initial> False >>> p.start() >>> print(p, p.is_alive()) <Process ... started> True >>> p.terminate() >>> time.sleep(0.1) >>> print(p, p.is_alive()) <Process ... stopped exitcode=-SIGTERM> False >>> p.exitcode == -signal.SIGTERM True exception multiprocessing. ProcessError ¶ Базовый класс всех исключений multiprocessing . exception multiprocessing. BufferTooShort ¶ Исключение, вызванное Connection.recv_bytes_into() , когда предоставленный объект буфера слишком мал для чтения сообщения. Если e является сущность BufferTooShort , то e.args[0] передаст сообщение в виде байтовой строки. exception multiprocessing. AuthenticationError ¶ Возникает при ошибке проверки подлинности. exception multiprocessing. TimeoutError ¶ Вызывается методами с тайм-аутом по истечении тайм-аута. Пайпы и очереди ¶ При использовании нескольких процессов обычно используют передачу сообщений для связи между процессами и избегают необходимости использования каких-либо примитивов синхронизации, таких как блокировки. Для передачи сообщений можно использовать Pipe() (для соединения между двумя процессами) или очередь (которая позволяет нескольким производителям и потребителям). Queue , SimpleQueue и типы JoinableQueue - мультипроизводитель, мультипотребитель очереди FIFO , смоделированные на классе queue.Queue в стандартной библиотеке. Они отличаются по тому Queue , испытывает недостаток в task_done() и методах join() , введенных в класс Python 2.5’s queue.Queue . Если вы используете JoinableQueue , то вы должны вызвать JoinableQueue.task_done() для каждой задачи, удаленной из очереди, или семафор используемый для подсчета количества незавершенных задач может в конечном итоге переполниться, вызывая исключение. Обратите внимание, что можно также создать общую очередь с помощью объекта менеджера - см. раздел Менеджеры . Примечание Когда объект помещен на очередь, объект - pickled и фон поток более поздние потоки данные pickled к основному пайп. Это имеет некоторые последствия, которые немного удивительны, но не должны вызывать никаких практических трудностей - если они действительно беспокоят вас, то вы можете вместо этого использовать очередь, созданную с manager . После помещения объекта в пустую очередь может произойти бесконечная задержка перед тем, как метод empty() очереди возвращает False и get_nowait() может возвращает без повышения queue.Empty . если несколько процессов ставят в очередь объекты, возможно, чтобы объекты были приняты на другом конце вне порядка. Однако объекты, поставленные в очередь одним и тем же процессом, всегда будут находиться в ожидаемом порядке относительно друг друга. Предупреждение Если процесс был убит с помощью Process.terminate() или os.kill() во время попытки использования Queue , то данные в очереди, вероятно, будут повреждены. Это может привести к тому, что любой другой процесс получит исключение при попытке использовать очередь позже. Предупреждение Как упомянуто выше, если дочерний процесс поместил предметы на очередь (и у него нет используемый JoinableQueue.cancel_join_thread ), тогда тот процесс не закончится, пока все буферизированные предметы не смылись (flushed) в пайп. Это означает, что при попытке присоединения к этому процессу может возникнуть взаимоблокировка, если вы не уверены, что все элементы, помещенные в очередь, были израсходованы. Аналогично, если дочерний процесс не является демоническим, то родительский процесс может зависать на выходе, когда пытается присоединиться ко всем своим недемоническим потомкам. Обратите внимание, что очередь, созданная с помощью менеджера, не имеет этой проблемы. См. Программирование рекомендаций . Пример использования очередей для межпроцессной связи см. в разделе Примеры . multiprocessing. Pipe ( [ duplex ] ) ¶ Возвращает пару (conn1, conn2) объектов Connection , представляющих концы пайпа. Если duplex равно True (по умолчанию), то пайп является двунаправленным. Если duplex - False тогда, пайп однонаправлен: conn1 может только быть используемый для получения сообщений, и conn2 может только быть используемый для отправки сообщений. class multiprocessing. Queue ( [ maxsize ] ) ¶ Возвращает общую очередь процесса, реализованную с использованием пайп и нескольких блокировок/семафоров. Когда процесс сначала помещает элемент в очередь, запускается питатель поток, который передает объекты из буфера в пайп. Обычные исключения queue.Empty и queue.Full из модуля queue стандартной библиотеки вызываются тайм-аутами сигнала. Queue реализует все методы queue.Queue , кроме task_done() и join() . qsize ( ) ¶ Возвращает приблизительный размер очереди. Из-за семантики многопоточной/многопроцессорной обработки это число не является надежным. Обратите внимание, что это может привести к появлению NotImplementedError на платформах Unix, таких как Mac OS X, где sem_getvalue() не реализован. empty ( ) ¶ Возвращает True , если очередь пуста, False иначе. Из-за семантики многопоточной/многопроцессорной обработки это ненадежно. full ( ) ¶ Возвращает True , если очередь полна, False иначе. Из-за семантики многопоточной/многопроцессорной обработки это ненадежно. put ( obj [ , block [ , timeout ] ] ) ¶ Поместить объект в очередь. Если дополнительный аргумент block имеет значение True (по умолчанию), а timeout - значение None (по умолчанию), при необходимости блокируйте до тех пор, пока свободный слот не будет доступен. Если timeout является положительным числом, он блокирует максимум timeout секунд и вызывает исключение queue.Full , если свободный слот не был доступен в течение этого времени. В противном случае ( block - False ) Поместить элемент в очередь, если свободный слот немедленно доступен, иначе вызовите исключение queue.Full ( timeout игнорируется в этом случае). put_nowait ( obj ) ¶ Эквивалентный put(obj, False) . get ( [ block [ , timeout ] ] ) ¶ Удаление и возвращает элемента из очереди. Если необязательными args block является True (по умолчанию), а timeout - None (по умолчанию), при необходимости блокируйте до тех пор, пока элемент не будет доступен. Если timeout является положительным числом, он блокирует максимум timeout секунд и вызывает исключение queue.Empty , если за это время не было доступно ни одного элемента. В противном случае (блок - False ), возвращает элемент, если он немедленно доступен, иначе вызовите исключение queue.Empty (в этом случае timeout игнорируется). Изменено в версии 3.8: Если очередь закрыта, ValueError поднят вместо OSError . get_nowait ( ) ¶ Эквивалентный get(False) . multiprocessing.Queue имеет несколько дополнительных методов, не найденных в queue.Queue . Эти методы обычно не нужны для большинства код: close ( ) ¶ Укажите, что текущий процесс больше не будет помещать данные в эту очередь. Фоновый поток завершит работу после очистки всех буферизованных данных в пайп. Это вызывается автоматически при сборе мусора в очередь. join_thread ( ) ¶ Присоединиться к фоновому потоку. Это может только быть используемый после того, как вызван close() . Это блокирует до фона выходы поток, гарантируя, что все данные в буфере смылись (flushed) в пайп. По умолчанию, если процесс не является создателем очереди, при выходе он попытается присоединиться к фоновому поток очереди. Процесс может вызвать cancel_join_thread() , чтобы заставить join_thread() ничего не делать. cancel_join_thread ( ) ¶ Препятствуйте тому, чтобы join_thread() блокировал. В частности, это предотвращает автоматическое соединение фоновых поток при завершении процесса – см. раздел join_thread() . Лучшее имя для этого метода может быть allow_exit_without_flush() . Вероятно, это приведет к потере поставленных в очередь данных, и вам почти наверняка не потребуется их использовать. Это действительно только в том случае, если необходимо, чтобы текущий процесс немедленно вышел, не дожидаясь очистки поставленных в очередь данных на основной пайп, и вы не заботитесь о потерянных данных. Примечание Функциональность этого класса требует функциональной реализации общего семафора в операционной системе хоста. Без него функциональность этого класса будет отключена, и попытки создания экземпляра Queue приведут к появлению ImportError . Дополнительные сведения см. в разделе bpo-3770 . То же самое относится и к любому из перечисленных ниже типов специализированных очередей. class multiprocessing. SimpleQueue ¶ Это упрощенный тип Queue , очень близкий к заблокированному Pipe . empty ( ) ¶ Возвращает True , если очередь пуста, False иначе. get ( ) ¶ Удаление и возвращает элемента из очереди. put ( item ) ¶ Поместить item в очередь. class multiprocessing. JoinableQueue ( [ maxsize ] ) ¶ JoinableQueue , Queue подкласс, представляет собой очередь, которая дополнительно содержит методы task_done() и join() . task_done ( ) ¶ Укажите, что ранее поставленная в очередь задача завершена. Используется потребителями очереди. Для каждого get() используемый, чтобы выбрать задачу, последующий вызов task_done() сообщает очереди, что обработка задачи завершена. Если join() в настоящее время заблокирует, то он возобновит, когда все предметы были обработаны (подразумевать, что требование task_done() было получено для каждого предмета, который был put() в очередь). Вызывает ValueError , если вызывается больше раз, чем было элементов, помещенных в очередь. join ( ) ¶ Блокировать до тех пор, пока все элементы в очереди не будут получены и обработаны. Количество незавершенных задач увеличивается при каждом добавлении элемента в очередь. Счетчик снижается всякий раз, когда потребитель звонит task_done() , чтобы указать, что элемент был извлечен, и вся работа над ним завершена. Когда число незавершенных задач падает до нуля, join() разблокирует. Разное ¶ multiprocessing. active_children ( ) ¶ Возвращает список всех живых потомков текущего процесса. Вызов этого метода имеет побочный эффект «присоединения» к любым уже завершенным процессам. multiprocessing. cpu_count ( ) ¶ Возвращает количество ЦПУ в системе. Это число не эквивалентно числу ЦПУ, которые может использовать текущий процесс. Количество используемых ЦПУ можно получить с помощью len(os.sched_getaffinity(0)) Может поднять NotImplementedError . multiprocessing. current_process ( ) ¶ Возвращает объект Process , соответствующий текущему процессу. Аналог threading.current_thread() . multiprocessing. parent_process ( ) ¶ Возвращает объект Process , соответствующий родительскому процессу current_process() . Для основного процесса parent_process будет None . Добавлено в версии 3.8. multiprocessing. freeze_support ( ) ¶ Добавление поддержки в том случае, если программа, использующая multiprocessing , была заморожена для создания исполняемого файла Windows. (Был проверен с помощью py2exe , PyInstaller и cx_Freeze .) Эту функцию необходимо вызвать непосредственно после if __name__ == '__main__' линии основного модуля. Например: from multiprocessing import Process , freeze_support def f (): print ( 'hello world!' ) if __name__ == '__main__' : freeze_support () Process ( target = f ) . start () Если строка freeze_support() опущена, то попытка запуска замороженного исполняемого файла вызовет RuntimeError . freeze_support() запроса не имеет никакого эффекта, когда он призван на любую операционную систему кроме Windows. Кроме того, если модулем управляет обычно Python интерпретатор на Windows (программа не была заморожена), то freeze_support() не имеет никакого эффекта. multiprocessing. get_all_start_methods ( ) ¶ Возвращает список поддерживаемых методов запуска, первым из которых является метод по умолчанию. Возможные методы запуска: 'fork' , 'spawn' и 'forkserver' . В Windows доступен только 'spawn' . На Unix 'fork' и 'spawn' всегда поддерживаются, при этом 'fork' - дефолт. Добавлено в версии 3.4. multiprocessing. get_context ( method=None ) ¶ Возвращает объект контекст, имеющий ту же атрибуты, что и модуль multiprocessing . Если method - None тогда дефолт, контекст - возвращенный. В противном случае method должны быть 'fork' , 'spawn' , 'forkserver' . ValueError возникает, если указанный метод запуска недоступен. Добавлено в версии 3.4. multiprocessing. get_start_method ( allow_none=False ) ¶ Возвращает имя метода запуска используемый для запуска процессов. Если метод начала не был исправлен, и allow_none ложный, то метод начала прикреплен к дефолту, и имя - возвращенный. Если метод запуска не был фиксирован, а allow_none имеет значение true, то None имеет значение возвращенный. возвращает значение может быть 'fork' , 'spawn' , 'forkserver' или None . 'fork' является значением по умолчанию в Unix, а 'spawn' - значением по умолчанию в Windows. Добавлено в версии 3.4. multiprocessing. set_executable ( ) ¶ Задает путь к Python интерпретатор, который будет использоваться при запуске дочернего процесса. (По умолчанию sys.executable - используемый). Встраивающие устройства, вероятно, должны будут сделать что-то вроде: set_executable ( os . path . join ( sys . exec_prefix , 'pythonw.exe' )) прежде чем они смогут создавать дочерние процессы. Изменено в версии 3.4: Теперь поддержанный на Unix, когда метод начала 'spawn' - используемый. multiprocessing. set_start_method ( method ) ¶ Установите метод, который должен быть используемый, чтобы начать дочерние процессы. method может быть 'fork' , 'spawn' или 'forkserver' . Следует отметить, что это должно вызываться не более одного раза и должно быть защищено внутри if __name__ == '__main__' клаузула основного модуля. Добавлено в версии 3.4. Объекты связи ¶ Объекты соединения позволяют отправлять и принимать выбираемые объекты или строки. Они могут рассматриваться как связанные сокеты, ориентированные на сообщение. Объекты соединения обычно создаются с помощью Pipe – см. также раздел Слушатели и клиенты . class multiprocessing.connection. Connection ¶ send ( obj ) ¶ Отправьте объект на другой конец соединения, который следует прочитать с помощью команды recv() . Объект должен быть подбираемым. Очень большие огурцы (приблизительно 32 MiB +, хотя это зависит от ОС) могут вызвать исключение ValueError . recv ( ) ¶ Возвращает объект, отправленный с другого конца соединения с помощью команды send() . Блокируется, пока не будет что получить. Поднимает EOFError , если ничего не осталось получить, а другой конец был закрыт. fileno ( ) ¶ Возвращает файл дескриптор или дескриптор используемый по соединению. close ( ) ¶ Закрыть связь. Это вызывается автоматически при сборе мусора соединения. poll ( [ timeout ] ) ¶ Возвращает, имеются ли данные, доступные для чтения. Если timeout не указан, то он будет возвращает немедленно. Если timeout - число, это указывает максимальное время блокировки в секундах. Если timeout None , то бесконечное время ожидания равно используемый. Следует отметить, что несколько объектов соединения могут опрашиваться одновременно с помощью функции multiprocessing.connection.wait() . send_bytes ( buffer [ , offset [ , size ] ] ) ¶ Отправка байтовых данных из байтоподобного объекта в виде полного сообщения. Если задано значение offset , то данные считываются из этой позиции в buffer . Если задано значение size , то многие байты будут считываться из буфера. Очень большие буферы (приблизительно 32 MiB +, хотя это зависит от ОС) могут вызвать исключение ValueError recv_bytes ( [ maxlength ] ) ¶ Возвращает полное сообщение байтовых данных, отправленное с другого конца соединения в виде строка. Блокируется, пока не будет что получить. Поднимает EOFError , если ничего не осталось получить, а другой конец закрылся. Если задано значение maxlength , и сообщение длиннее maxlength , то OSError возникает, и соединение будет недоступно для чтения. Изменено в версии 3.3: Используемая функция поднимает IOError , которое теперь является алиасом OSError . recv_bytes_into ( buffer [ , offset ] ) ¶ Считывание в buffer полного сообщения байтовых данных, отправленных с другого конца соединения, и возвращает количества байтов в сообщении. Блокируется, пока не будет что получить. Поднимает EOFError , если ничего не осталось получить, а другой конец был закрыт. buffer должен быть записываемым байтоподобным объектом . Если задано значение offset , то сообщение будет записано в буфер из этой позиции. Смещение должно быть неотрицательным целым числом, меньшим длины buffer (в байтах). Если буфер слишком короткий, то возникает исключение BufferTooShort и полное сообщение доступно как e.args[0] где e - исключение сущность. Изменено в версии 3.3: Сами объекты соединения теперь могут переноситься между процессами с помощью Connection.send() и Connection.recv() . Например: >>> >>> from multiprocessing import Pipe >>> a , b = Pipe () >>> a . send ([ 1 , 'hello' , None ]) >>> b . recv () [1, 'hello', None] >>> b . send_bytes ( b 'thank you' ) >>> a . recv_bytes () b'thank you' >>> import array >>> arr1 = array . array ( 'i' , range ( 5 )) >>> arr2 = array . array ( 'i' , [ 0 ] * 10 ) >>> a . send_bytes ( arr1 ) >>> count = b . recv_bytes_into ( arr2 ) >>> assert count == len ( arr1 ) * arr1 . itemsize >>> arr2 array('i', [0, 1, 2, 3, 4, 0, 0, 0, 0, 0]) Предупреждение Метод Connection.recv() автоматически отключает полученные данные, что может быть угрозой безопасности, если вы не можете доверять процессу, отправившему сообщение. Поэтому, если объект подключения не был создан с помощью Pipe() , следует использовать методы recv() и send() только после выполнения той или иной аутентификации. См. Ключи аутентификации . Предупреждение Если процесс погибает, когда он пытается прочитать или записать в пайп, то данные в пайп, вероятно, будут повреждены, поскольку может оказаться невозможным убедиться, где лежат границы сообщения. Примитивы синхронизации ¶ Обычно примитивы синхронизации не так необходимы в многопроцессорной программе, как в многопоточной программе. См. документацию по модулю threading . Обратите внимание, что можно также создать примитивы синхронизации с помощью объекта менеджера - см. раздел Менеджеры . class multiprocessing. Barrier ( parties [ , action [ , timeout ] ] ) ¶ Объект барьер: клон threading.Barrier . Добавлено в версии 3.3. class multiprocessing. BoundedSemaphore ( [ value ] ) ¶ Барьерный семафорный объект: близкий аналог threading.BoundedSemaphore . Существует одиночное отличие от его близкого аналога: первый аргумент его метода acquire называется block , как это согласуется с Lock.acquire() . Примечание В Mac OS X это неотличимо от Semaphore , потому что sem_getvalue() не реализована на этой платформе. class multiprocessing. Condition ( [ lock ] ) ¶ Переменная условия: алиас для threading.Condition . Если задано значение lock , то это должен быть объект Lock или RLock из multiprocessing . Изменено в версии 3.3: Добавлен метод wait_for() . class multiprocessing. Event ¶ Клон threading.Event . class multiprocessing. Lock ¶ Нерекурсивный объект блокировки: близкий аналог threading.Lock . Как только процесс или поток приобрел блокировку, последующие попытки получить ее от любого процесса или поток будут блокироваться до тех пор, пока она не будет освобождена; любой процесс или поток может освободить его. Понятия и поведение threading.Lock в том виде, в каком они применяются к потоки, воспроизводятся здесь в multiprocessing.Lock , как это применимо к процессам или потоки, за исключением отмеченных. Обратите внимание, что Lock - на самом деле фабричная функция, какой возвращает сущность multiprocessing.synchronize.Lock инициализировал с дефолтом контекст. Lock поддерживает протокол контекстного менеджера и таким образом может быть используемый в with инструкции. acquire ( block=True , timeout=None ) ¶ Получить блокировку, блокировку или неблокировку. Если для аргумента block установлено значение True (значение по умолчанию), вызов метода будет блокироваться до тех пор, пока блокировка не окажется в разблокированном состояние, а затем будет установлен параметр locked и возвращает True . Обратите внимание, что имя этого первого аргумента отличается от имени в threading.Lock.acquire() . Если для аргумента block установлено значение False , вызов метода не блокируется. Если блокировка в данный момент находится в заблокированном состояние, возвращает False ; в противном случае установите блокировку на заблокированный состояние и возвращает True . При вызове с положительным значение с плавающей запятой для timeout блок максимум на количество секунд, указанное параметром timeout , если блокировка не может быть получена. Просьбы с отрицательным значение для timeout эквивалентны timeout ноля. Вызовы с timeout значение None (по умолчанию) устанавливают период тайм-аута как бесконечный. Отметим, что лечение отрицательного или None значения для timeout отличается от реализованного поведения в threading.Lock.acquire() . Аргумент timeout не имеет практических последствий, если аргумент block имеет значение False и, таким образом, игнорируется. Возвращает True если блокировка была приобретена или False , если истек период ожидания. release ( ) ¶ Отпустите замок. Это может быть вызвано из любого процесса или поток, а не только из процесса или поток, которые первоначально приобрели блокировку. Поведение аналогично поведению в threading.Lock.release() , за исключением того, что при вызове на разблокированной блокировке возникает ValueError . class multiprocessing. RLock ¶ Объект рекурсивной блокировки: близкий аналог threading.RLock . Рекурсивная блокировка должна быть разблокирована процессом или поток, получившим ее. Как только процесс или поток приобрел рекурсивную блокировку, тот же самый процесс или поток может снова получить ее без блокировки; этот процесс или поток должны выпускать его один раз в каждый раз, когда он был приобретен. Обратите внимание, что RLock - на самом деле фабричная функция, какой возвращает сущность multiprocessing.synchronize.RLock инициализировал с дефолтом контекст. RLock поддерживает протокол контекстного менеджера и таким образом может быть используемый в with инструкции. acquire ( block=True , timeout=None ) ¶ Получить блокировку, блокировку или неблокировку. При вызове с аргументом block , имеющим значение True , блокировать до тех пор, пока блокировка не окажется в разблокированном состояние (не принадлежащем какому-либо процессу или поток), пока блокировка уже не принадлежит текущему процессу или поток. Текущий процесс или поток затем получает право собственности на блокировку (если она еще не имеет права собственности), а уровень рекурсии внутри блокировки увеличивается на единицу, что приводит к возвращает значение True . Обратите внимание, что в поведении этого первого аргумента существует несколько различий по сравнению с реализацией threading.RLock.acquire() , начиная с имени самого аргумента. При вызове с аргументом block , имеющим значение False , не блокируйте. Если замок был уже приобретен (и таким образом принадлежит) другим процессом или поток, текущий процесс или поток не берут собственность, и уровень рекурсии в замке не изменен, приведя к возвращает значение False . Если блокировка находится в разблокированном состояние, текущий процесс или поток становится владельцем и уровень рекурсии увеличивается, что приводит к возвращает значение True . Использование и поведение аргумента timeout такие же, как и в Lock.acquire() . Обратите внимание, что некоторые из этих поведений timeout отличаются от реализованных поведений в threading.RLock.acquire() . release ( ) ¶ Разблокируйте блокировку, уменьшая уровень рекурсии. Если после уменьшения уровень рекурсии равен нулю, сбросьте блокировку на разблокированную (не принадлежащую какому-либо процессу или поток) и если какие-либо другие процессы или потоки заблокированы в ожидании разблокировки блокировки, разрешите выполнение только одного из них. Если после уменьшения уровень рекурсии остается ненулевым, блокировка остается заблокированной и принадлежит вызывающему процессу или поток. Только назовите этот метод, когда процесс запроса или поток будут владеть замком. AssertionError поднят, если этот метод называют процесс или поток кроме владельца или если замок находится в незапертом (ненаходящемся в собственности) состояние. Обратите внимание, что тип исключения, вызванного в этой ситуации, отличается от реализованного поведения в threading.RLock.release() . class multiprocessing. Semaphore ( [ value ] ) ¶ Семафорный объект: близкий аналог threading.Semaphore . Существует одиночное отличие от его близкого аналога: первый аргумент его метода acquire называется block , как это согласуется с Lock.acquire() . Примечание В Mac OS X sem_timedwait не поддерживается, поэтому вызов acquire() с тайм-аутом будет эмулировать поведение этой функции с помощью спящего цикла. Примечание Если сигнал SIGINT, сгенерированный Ctrl-C , прибудет, в то время как главный поток заблокирован требованием к BoundedSemaphore.acquire() , Lock.acquire() , RLock.acquire() , Semaphore.acquire() , Condition.acquire() или Condition.wait() тогда, требование будет немедленно прервано, и KeyboardInterrupt будет поднят. Это отличается от поведения threading , где SIGINT будет игнорироваться во время выполнения эквивалентных блокирующих вызовов. Примечание Некоторые функциональные возможности этого пакета требуют функциональной реализации общего семафора в операционной системе хоста. Без него модуль multiprocessing.synchronize будет отключен, и попытки его импорта приведут к появлению ImportError . Дополнительные сведения см. в разделе bpo-3770 . Разделенные объекты ctypes ¶ С помощью общей памяти можно создавать общие объекты, которые могут наследоваться дочерними процессами. multiprocessing. Value ( typecode_or_type , *args , lock=True ) ¶ Возвращает объект ctypes , выделенный из общей памяти. По умолчанию возвращает значение фактически является синхронизированной оболочкой для объекта. К самому объекту можно получить доступ через value атрибут Value . typecode_or_type определяет тип объекта возвращенный: это - или тип ctypes или один символ typecode доброго используемый модулем array . *args передан конструктору для типа. Если lock равно True (по умолчанию), создается новый объект рекурсивной блокировки для синхронизации доступа к значение. Если lock является объектом Lock или RLock , то это будет используемый для синхронизации доступа к значение. Если lock будет False тогда, то доступ к объекту возвращенный не будет автоматически защищен замком, таким образом, это не обязательно будет «безопасно от процесса». Операции как += , которые включают прочитанный и пишут, не атомные. Так что, если для сущность, вы хотите атомарно увеличить общий значение это недостаточно, чтобы просто сделать: counter . value += 1 Предполагая, что связанная блокировка является рекурсивной (что по умолчанию), можно сделать: with counter . get_lock (): counter . value += 1 Обратите внимание, что lock является только ключевым аргументом. multiprocessing. Array ( typecode_or_type , size_or_initializer , * , lock=True ) ¶ Возвращает массив ctypes, выделенный из общей памяти. По умолчанию возвращает значение фактически является синхронизированной обёрткой для массива. typecode_or_type определяет тип элементов множества возвращенный: это - или тип ctypes или один символ typecode доброго используемый модулем array . Если size_or_initializer является целым числом, то он определяет длину массива, и массив будет первоначально обнулен. Иначе size_or_initializer - последовательность, которая является используемый, чтобы инициализировать множество и чья длина определяет длину множества. Если lock равно True (по умолчанию), создается новый объект блокировки для синхронизации доступа к значение. Если lock является объектом Lock или RLock , то это будет используемый для синхронизации доступа к значение. Если lock будет False тогда, то доступ к объекту возвращенный не будет автоматически защищен замком, таким образом, это не обязательно будет «безопасно от процесса». Обратите внимание, что lock - ключевой только аргумент. Обратите внимание, что у множества ctypes.c_char есть value и raw атрибуты, которые позволяют использовать его, чтобы сохранить и восстановить строки. Модуль multiprocessing.sharedctypes ¶ Модуль multiprocessing.sharedctypes предоставляет функции для выделения объектов ctypes из общей памяти, которые могут быть унаследованы дочерними процессами. Примечание Хотя можно сохранить указатель в общей памяти, помните, что это относится к расположению в адресном пространстве конкретного процесса. Однако указатель, вероятно, недействителен в контекст второго процесса, и попытка отсоединить указатель от второго процесса может вызвать сбой. multiprocessing.sharedctypes. RawArray ( typecode_or_type , size_or_initializer ) ¶ Возвращает массив ctypes, выделенный из общей памяти. typecode_or_type определяет тип элементов множества возвращенный: это - или тип ctypes или один символ typecode доброго используемый модулем array . Если size_or_initializer является целым числом, то он определяет длину массива, и массив будет первоначально обнулен. Иначе size_or_initializer - последовательность, которая является используемый, чтобы инициализировать множество и чья длина определяет длину множества. Обратите внимание, что настройка и получение элемента потенциально неатомны - вместо этого используйте команду Array() , чтобы убедиться, что доступ автоматически синхронизирован с помощью блокировки. multiprocessing.sharedctypes. RawValue ( typecode_or_type , *args ) ¶ Возвращает объект ctypes, выделенный из общей памяти. typecode_or_type определяет тип объекта возвращенный: это - или тип ctypes или один символ typecode доброго используемый модулем array . *args передан конструктору для типа. Обратите внимание, что настройка и получение значение потенциально неатомны - вместо этого используйте Value() , чтобы убедиться, что доступ автоматически синхронизирован с помощью блокировки. Обратите внимание, что массив ctypes.c_char имеет value и raw атрибуты, которые позволяют использовать его для хранения и извлечения строки - см. документацию для ctypes . multiprocessing.sharedctypes. Array ( typecode_or_type , size_or_initializer , * , lock=True ) ¶ То же как RawArray() за исключением того, что в зависимости от значение lock безопасная от процесса обертка синхронизации может быть возвращенный вместо сырья ctypes множество. Если lock равно True (по умолчанию), создается новый объект блокировки для синхронизации доступа к значение. Если lock является объектом Lock или RLock , то это будет используемый для синхронизации доступа к значение. Если lock будет False тогда, то доступ к объекту возвращенный не будет автоматически защищен замком, таким образом, это не обязательно будет «безопасно от процесса». Обратите внимание, что lock является толко ключевым аргументом. multiprocessing.sharedctypes. Value ( typecode_or_type , *args , lock=True ) ¶ То же как RawValue() за исключением того, что в зависимости от значение lock безопасная от процесса обертка синхронизации может быть возвращенный вместо сырья ctypes объект. Если lock равно True (по умолчанию), создается новый объект блокировки для синхронизации доступа к значение. Если lock является объектом Lock или RLock , то это будет используемый для синхронизации доступа к значение. Если lock будет False тогда, то доступ к объекту возвращенный не будет автоматически защищен замком, таким образом, это не обязательно будет «безопасно от процесса». Обратите внимание, что lock является только ключевым аргументом. multiprocessing.sharedctypes. copy ( obj ) ¶ Возвращает объект ctypes, выделенный из общей памяти, который является копией объекта ctypes obj . multiprocessing.sharedctypes. synchronized ( obj [ , lock ] ) ¶ Возвращает безопасный для процесса объект-обертка для объекта ctypes, который использует lock для синхронизации доступа. Если lock имеет значение None (по умолчанию), то объект multiprocessing.RLock создается автоматически. Синхронизированная обертка будет иметь два метода в дополнение к методам обертываемого объекта: get_obj() возвращает обертываемый объект и get_lock() возвращает блокируемый объект используемый для синхронизации. Обратите внимание, что доступ к объекту ctypes через оболочку может быть намного медленнее, чем доступ к объекту raw ctypes. Изменено в версии 3.5: Синхронизированные объекты поддерживают протокол менеджера контекста . В приведенной ниже таблице сравнивается синтаксис создания общих объектов ctypes из общей памяти с синтаксисом обычных ctypes. (В таблице MyStruct представлена некоторая подкласс ctypes.Structure . ctypes sharedctypes используя тип sharedctypes используя typecode c_double(2.4) RawValue(c_double, 2.4) RawValue(„d“, 2.4) MyStruct(4, 6) RawValue(MyStruct, 4, 6)   (c_short * 7)() RawArray(c_short, 7) RawArray(„h“, 7) (c_int * 3)(9, 2, 8) RawArray(c_int, (9, 2, 8)) RawArray(„i“, (9, 2, 8)) Ниже приведен пример, когда ряд объектов ctypes изменяется дочерним процессом: from multiprocessing import Process , Lock from multiprocessing.sharedctypes import Value , Array from ctypes import Structure , c_double class Point ( Structure ): _fields_ = [( 'x' , c_double ), ( 'y' , c_double )] def modify ( n , x , s , A ): n . value **= 2 x . value **= 2 s . value = s . value . upper () for a in A : a . x **= 2 a . y **= 2 if __name__ == '__main__' : lock = Lock () n = Value ( 'i' , 7 ) x = Value ( c_double , 1.0 / 3.0 , lock = False ) s = Array ( 'c' , b 'hello world' , lock = lock ) A = Array ( Point , [( 1.875 , - 6.25 ), ( - 5.75 , 2.0 ), ( 2.375 , 9.5 )], lock = lock ) p = Process ( target = modify , args = ( n , x , s , A )) p . start () p . join () print ( n . value ) print ( x . value ) print ( s . value ) print ([( a . x , a . y ) for a in A ]) Результаты напечатаны: 49 0.1111111111111111 HELLO WORLD [(3.515625, 39.0625), (33.0625, 4.0), (5.640625, 90.25)] Менеджеры ¶ Менеджеры предоставляют способ создания данных, которые могут совместно использоваться различными процессами, включая совместное использование по сети между процессами, работающими на разных машинах. Объект-менеджер управляет серверным процессом, который управляет shared objects . Другие процессы могут обращаться к общим объектам с помощью прокси. multiprocessing. Manager ( ) ¶ Возвращает начатый объект SyncManager , который может быть используемый для разделения объектов между процессами. Объект менеджера возвращенный соответствует порожденному дочернему процессу и имеет методы, которые создадут общие объекты и соответствующие возвращаемое прокси. Процессы менеджера будут остановлены сразу после сбора мусора или завершения родительского процесса. Классы менеджера определяются в модуле multiprocessing.managers : class multiprocessing.managers. BaseManager ( [ address [ , authkey ] ] ) ¶ Создайте объект BaseManager. После создания необходимо вызвать start() или get_server().serve_forever() , чтобы гарантировать, что объект менеджера ссылается на запущенный процесс менеджера. address - адрес, по которому процесс менеджера прослушивает новые подключения. Если address None , то выбирается произвольная. authkey - ключ идентификации, который будет используемый, чтобы проверить законность поступающих связей с процессом сервера. Если authkey - None тогда, current_process().authkey - используемый. В противном случае authkey является используемый и должен быть байтом строка. start ( [ initializer [ , initargs ] ] ) ¶ Начните подпроцессы, чтобы начать менеджера. Если initializer не является None , то подпроцессы вызовет initializer(*initargs) при запуске. get_server ( ) ¶ Возвращает объект Server , представляющий фактический сервер под управлением менеджера. Объект Server поддерживает метод serve_forever() : >>> >>> from multiprocessing.managers import BaseManager >>> manager = BaseManager ( address = ( '' , 50000 ), authkey = b 'abc' ) >>> server = manager . get_server () >>> server . serve_forever () Server дополнительно содержит address атрибут. connect ( ) ¶ Подключить объект локального менеджера к процессу удаленного менеджера: >>> >>> from multiprocessing.managers import BaseManager >>> m = BaseManager ( address = ( '127.0.0.1' , 50000 ), authkey = b 'abc' ) >>> m . connect () shutdown ( ) ¶ Остановить процесс используемый менеджером. Это только доступно, если start() был используемый, чтобы начать процесс сервера. Это можно вызвать несколько раз. register ( typeid [ , callable [ , proxytype [ , exposed [ , method_to_typeid [ , create_method ] ] ] ] ] ) ¶ classmethod, который может быть используемый для регистрации типа или подлежащий выкупу с классом менеджера. typeid - «идентификатор типа», который является используемый, чтобы определить особый тип общего объекта. Это должно быть строка. callable является вызываемым используемый для создания объектов для этого идентификатора типа. Если диспетчер сущность будет подключен к серверу с помощью метода connect() или если аргумент create_method имеет значение False , его можно оставить как None . proxytype является подкласс BaseProxy , который используемый для создания прокси для общих объектов с этим typeid . Если None , то класс прокси создается автоматически. exposed - используемый, чтобы определить последовательность вызова метода, которые прокси для этого typeid нужно разрешить доступу, используя BaseProxy._callmethod() . (Если exposed - None тогда, proxytype._exposed_ - используемый вместо этого, если он существует.) в случае, если не указан список разоблаченных объектов, будут доступны все «публичные методы» общего объекта. (Здесь «метод публичный» означает любой атрибут, у которого есть метод __call__() и чьё имя не начинается с '_' .) method_to_typeid - отображение используемый, чтобы определить тип возвращает тех выставленных методов, которые должны возвращает прокси. Это наносит на карту названия метода к typeid строки. (Если method_to_typeid - None тогда, proxytype._method_to_typeid_ - используемый вместо этого, если он существует.) Если вызов метода не будет ключом этого отображения или если отображение будет None тогда объект, то возвращенный методом будет скопирован значение. create_method определяет, должен ли метод быть создан с именем typeid , который может быть используемый, чтобы сказать процессу сервера создавать новый общий объект и возвращает прокси для него. По умолчанию это значение равно True . BaseManager сущности также имеют одно свойство только для чтения: address ¶ Адрес, используемый менеджером. Изменено в версии 3.3: Объекты менеджера поддерживают протокол управления контекст - см. раздел Типы менеджера контекста . __enter__() запускает процесс сервера (если он еще не запущен), а затем возвращает объект диспетчера. __exit__() вызовы shutdown() . В предыдущих версиях __enter__() не запускал серверный процесс диспетчера, если он еще не был запущен. class multiprocessing.managers. SyncManager ¶ Подкласс BaseManager , который может быть используемый для синхронизации процессов. Объекты этого типа возвращенный multiprocessing.Manager() . Его методы обычно создают и возвращает Прокси объекты для многих типы данных используемый, которые будут синхронизированы через процессы. Это, в частности, включает общие списки и словари. Barrier ( parties [ , action [ , timeout ] ] ) ¶ Создание общего объекта threading.Barrier и возвращает прокси для него. Добавлено в версии 3.3. BoundedSemaphore ( [ value ] ) ¶ Создание общего объекта threading.BoundedSemaphore и возвращает прокси для него. Condition ( [ lock ] ) ¶ Создание общего объекта threading.Condition и возвращает прокси для него. Если задано значение lock , то оно должно быть прокси для объекта threading.Lock или threading.RLock . Изменено в версии 3.3: Добавлен метод wait_for() . Event ( ) ¶ Создание общего объекта threading.Event и возвращает прокси для него. Lock ( ) ¶ Создание общего объекта threading.Lock и возвращает прокси для него. Namespace ( ) ¶ Создание общего объекта Namespace и возвращает прокси для него. Queue ( [ maxsize ] ) ¶ Создание общего объекта queue.Queue и возвращает прокси для него. RLock ( ) ¶ Создание общего объекта threading.RLock и возвращает прокси для него. Semaphore ( [ value ] ) ¶ Создание общего объекта threading.Semaphore и возвращает прокси для него. Array ( typecode , sequence ) ¶ Создайте массив и возвращает прокси-сервер для него. Value ( typecode , value ) ¶ Создайте объект с возможностью записи value атрибут и возвращает прокси для него. dict ( ) ¶ dict ( mapping ) dict ( sequence ) Создание общего объекта dict и возвращает прокси для него. list ( ) ¶ list ( sequence ) Создание общего объекта list и возвращает прокси для него. Изменено в версии 3.6: Общие объекты могут быть вложены. Например, объект общего контейнера, такой как общий список, может содержать другие общие объекты, которые будут управляться и синхронизироваться SyncManager . class multiprocessing.managers. Namespace ¶ Тип, который может регистрироваться в SyncManager . Объект пространства имен не имеет публичных методов, но содержит записываемые атрибуты. Его представление показывает значения его атрибутов. Однако при использовании прокси для объекта пространства имен атрибут, начинающийся с '_' , будет атрибут прокси, а не атрибут ссылки: >>> >>> manager = multiprocessing . Manager () >>> Global = manager . Namespace () >>> Global . x = 10 >>> Global . y = 'hello' >>> Global . _z = 12.3 # это атрибут прокси >>> print ( Global ) Namespace(x=10, y='hello') Настраиваемые менеджеры ¶ Для создания собственного менеджера создается подкласс BaseManager и используется классметод register() для регистрации новых типов или вызываемых объектов в классе менеджера. Например: from multiprocessing.managers import BaseManager class MathsClass : def add ( self , x , y ): return x + y def mul ( self , x , y ): return x * y class MyManager ( BaseManager ): pass MyManager . register ( 'Maths' , MathsClass ) if __name__ == '__main__' : with MyManager () as manager : maths = manager . Maths () print ( maths . add ( 4 , 3 )) # prints 7 print ( maths . mul ( 7 , 8 )) # prints 56 Использование удаленного менеджера ¶ Можно запускать сервер менеджера на одной машине и использовать его клиентами с других машин (при условии, что соответствующие брандмауэры разрешают это). Выполнение следующих команд создает сервер для одной общей очереди, к которой могут иметь доступ удаленные клиенты: >>> >>> from multiprocessing.managers import BaseManager >>> from queue import Queue >>> queue = Queue () >>> class QueueManager ( BaseManager ): pass >>> QueueManager . register ( 'get_queue' , callable = lambda : queue ) >>> m = QueueManager ( address = ( '' , 50000 ), authkey = b 'abracadabra' ) >>> s = m . get_server () >>> s . serve_forever () Один клиент может получить доступ к серверу следующим образом: >>> >>> from multiprocessing.managers import BaseManager >>> class QueueManager ( BaseManager ): pass >>> QueueManager . register ( 'get_queue' ) >>> m = QueueManager ( address = ( 'foo.bar.org' , 50000 ), authkey = b 'abracadabra' ) >>> m . connect () >>> queue = m . get_queue () >>> queue . put ( 'hello' ) Его также может использовать другой клиент: >>> >>> from multiprocessing.managers import BaseManager >>> class QueueManager ( BaseManager ): pass >>> QueueManager . register ( 'get_queue' ) >>> m = QueueManager ( address = ( 'foo.bar.org' , 50000 ), authkey = b 'abracadabra' ) >>> m . connect () >>> queue = m . get_queue () >>> queue . get () 'hello' Локальные процессы также могут обращаться к этой очереди, используя код сверху на клиенте для удаленного доступа к ней: >>> >>> from multiprocessing import Process , Queue >>> from multiprocessing.managers import BaseManager >>> class Worker ( Process ): ... def __init__ ( self , q ): ... self . q = q ... super ( Worker , self ) . __init__ () ... def run ( self ): ... self . q . put ( 'local hello' ) ... >>> queue = Queue () >>> w = Worker ( queue ) >>> w . start () >>> class QueueManager ( BaseManager ): pass ... >>> QueueManager . register ( 'get_queue' , callable = lambda : queue ) >>> m = QueueManager ( address = ( '' , 50000 ), authkey = b 'abracadabra' ) >>> s = m . get_server () >>> s . serve_forever () Прокси объекты ¶ Прокси - объект, какой относится к общему объекту, который живет (по- видимому), в другом процессе. Говорят, что общий объект является ссылкой прокси. Несколько прокси-объектов могут иметь один и тот же ссылочный объект. Прокси-объект содержат методы, которые вызывают соответствующие методы его ссылки (хотя не каждый метод ссылки обязательно будет доступен через прокси). Таким образом, прокси может быть используемый так же, как его референт: >>> >>> from multiprocessing import Manager >>> manager = Manager () >>> l = manager . list ([ i * i for i in range ( 10 )]) >>> print ( l ) [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>> print ( repr ( l )) <ListProxy object, typeid 'list' at 0x...> >>> l [ 4 ] 16 >>> l [ 2 : 5 ] [4, 9, 16] Заметьте, что применение str() прокси будет возвращает представление референта, тогда как применение repr() будет возвращает представление прокси. Важной особенностью прокси-объектов является то, что они могут быть переданы между процессами. Таким образом, референт может содержать Прокси объекты . Это разрешает вложение этих управляемых списков, словари и другого Прокси объекты : >>> >>> a = manager . list () >>> b = manager . list () >>> a . append ( b ) # ссылка a теперь содержит ссылку b >>> print ( a , b ) [<ListProxy object, typeid 'list' at ...>] [] >>> b . append ( 'hello' ) >>> print ( a [ 0 ], b ) ['hello'] ['hello'] Аналогично, прокси словарь и списка могут быть вложены друг в друга: >>> >>> l_outer = manager . list ([ manager . dict () for i in range ( 2 ) ]) >>> d_first_inner = l_outer [ 0 ] >>> d_first_inner [ 'a' ] = 1 >>> d_first_inner [ 'b' ] = 2 >>> l_outer [ 1 ][ 'c' ] = 3 >>> l_outer [ 1 ][ 'z' ] = 26 >>> print ( l_outer [ 0 ]) {'a': 1, 'b': 2} >>> print ( l_outer [ 1 ]) {'c': 3, 'z': 26} Если стандартные (не прокси) list или dict объекты содержатся в ссылке, изменения этих изменяемых значения не будут распространяться через менеджер, поскольку прокси не может знать, когда изменятся содержащиеся в них значения. Однако хранение значение в контейнерном прокси (который вызывает __setitem__ на объекте по доверенности) действительно размножается через менеджера и так эффективно изменить такой предмет, можно было повторно назначить измененный значение контейнерному прокси: # создать список прокси и добавить изменяемый объект (словарь) lproxy = manager . list () lproxy . append ({}) # теперь изменяемый словарь d = lproxy [ 0 ] d [ 'a' ] = 1 d [ 'b' ] = 2 # на этом этапе изменения d еще не синхронизируются, но при обновлении словаря # прокси уведомляется об изменении lproxy [ 0 ] = d Этот подход, возможно, менее удобен, чем использование вложенных Прокси объекты в большинстве случаев использования, но также демонстрирует уровень управления синхронизацией. Примечание Прокси-типы в multiprocessing не поддерживают сравнения по значение. Итак, для сущность у нас есть: >>> >>> manager . list ([ 1 , 2 , 3 ]) == [ 1 , 2 , 3 ] False Вместо этого следует использовать копию ссылки при проведении сравнений. class multiprocessing.managers. BaseProxy ¶ Объекты по доверенности - сущности подклассы BaseProxy . _callmethod ( methodname [ , args [ , kwds ] ] ) ¶ Вызов и возвращает результата метода ссылки прокси. Если proxy - прокси, ссылочным элементом которого является obj , то выражение: proxy . _callmethod ( methodname , args , kwds ) вычислит выражение: getattr ( obj , methodname )( * args , ** kwds ) в процессе менеджере. возвращенный значение будет копией результата вызова или прокси для нового общего объекта - см. документацию для аргумента method_to_typeid BaseManager.register() . Если в результате вызова возникает исключение, то вызов повторно инициируется функцией _callmethod() . Если в процессе менеджера возникает другое исключение, оно преобразуется в исключение RemoteError и инициируется _callmethod() . Обратите внимание, в частности, на то, что исключение будет создано, если methodname не было exposed . Пример использования _callmethod() : >>> >>> l = manager . list ( range ( 10 )) >>> l . _callmethod ( '__len__' ) 10 >>> l . _callmethod ( '__getitem__' , ( slice ( 2 , 7 ),)) # equivalent to l[2:7] [2, 3, 4, 5, 6] >>> l . _callmethod ( '__getitem__' , ( 20 ,)) # equivalent to l[20] Traceback (most recent call last): ... IndexError : list index out of range _getvalue ( ) ¶ Возвращает копию референта. Если референт не может быть выбран, это вызовет исключение. __repr__ ( ) ¶ Возвращает представление прокси-объекта. __str__ ( ) ¶ Возвращает представление референта. Очистка ¶ Объект по доверенности использует weakref колбэк так, чтобы, когда это собрало мусор, он вычеркнул из списка себя от менеджера, который владеет его референтом. Общий объект удаляется из процесса диспетчера, если на него больше не ссылается ни один прокси. Процессные пулы ¶ Можно создать пул процессов, который будет выполнять задачи, переданные ему с классом Pool . class multiprocessing.pool. Pool ( [ processes [ , initializer [ , initargs [ , maxtasksperchild [ , context ] ] ] ] ] ) ¶ Объект пула процессов, который управляет пулом рабочих процессов, в который могут отправляться задания. Он поддерживает асинхронные результаты с тайм-аутами и колбэки и имеет параллельную реализацию карты. processes - количество используемых рабочих процессов. Если processes None , то число возвращенный по os.cpu_count() равно используемый. Если initializer не является None , то каждый рабочий процесс будет вызывать initializer(*initargs) при запуске. maxtasksperchild - количество задач, которые рабочий процесс может выполнить до выхода и замены новым рабочим процессом для освобождения неиспользуемых ресурсов. Дефолт maxtasksperchild - None , что означает процессы рабочего, будет жить пока бассейн. context может быть используемый, чтобы определить контекст используемый для старта процессов рабочего. Обычно пул создается с помощью функции multiprocessing.Pool() или метода Pool() объекта контекст. В обоих случаях context устанавливается соответствующим образом. Следует отметить, что методы объекта пула должны вызываться только процессом, создавшим пул. Предупреждение multiprocessing.pool объекты имеют внутренние ресурсы, которыми необходимо правильно управлять (как и любой другой ресурс), используя пул в качестве менеджера контекст или вызывая close() и terminate() вручную. Неспособность сделать это может привести к зависанию процесса при завершении. Обратите внимание, что это не верно , чтобы полагаться на сборщик мусора, чтобы уничтожить пул, так как CPython не гарантирует, что финализатор пула будет вызван (см. object.__del__() для получения дополнительной информации). Добавлено в версии 3.2: maxtasksperchild Добавлено в версии 3.4: context Примечание Рабочие процессы внутри Pool обычно работают в течение всей продолжительности рабочей очереди пула. Частый шаблон, встречающийся в других системах (таких как Apache, mod_wsgi и т.д.) для освобождения ресурсов, находящихся в распоряжении работников, заключается в том, чтобы позволить работнику в пуле выполнить только определенный объем работы перед выходом, очисткой и новым процессом, который должен заменить старый. Аргумент maxtasksperchild Pool предоставляет эту возможность конечному пользователю. apply ( func [ , args [ , kwds ] ] ) ¶ Вызовите func с аргументами args и ключевой аргументы kwds . Он блокируется до тех пор, пока результат не будет готов. Учитывая эти блоки, apply_async() лучше подходит для выполнения работы параллельно. Кроме того, func выполняется только в одном из работников пула. apply_async ( func [ , args [ , kwds [ , callback [ , error_callback ] ] ] ] ) ¶ Вариант метода apply() , который возвращает объект AsyncResult . Если задан параметр callback , то он должен быть вызываемым и принимать один аргумент. То, когда результат становится готовым callback , применено к нему, это - то, если неудавшееся требование, в этом случае error_callback не применен вместо этого. Если задан параметр error_callback , то он должен быть вызываемым и принимать один аргумент. Если целевая функция терпит неудачу, то error_callback называют за исключением сущность. Обратные вызовы должны быть завершены немедленно, поскольку в противном случае поток, обрабатывающая результаты, будет заблокирована. map ( func , iterable [ , chunksize ] ) ¶ Параллельный эквивалент встроенной функции map() (однако он поддерживает только один аргумент iterable для нескольких итерабелей см. starmap() ). Он блокируется до тех пор, пока результат не будет готов. Этот метод разбивает итабль на несколько чанки, которые он передает в пул процессов как отдельные задачи. (Приблизительный) размер этих чанки можно задать, установив для параметра chunksize положительное целое число. Обратите внимание, что это может привести к интенсивному использованию памяти для очень длинных итераблей. Рассмотрите возможность использования imap() или imap_unordered() с явным параметром chunksize для повышения эффективности. map_async ( func , iterable [ , chunksize [ , callback [ , error_callback ] ] ] ) ¶ Вариант метода map() , который возвращает объект AsyncResult . Если задан параметр callback , то он должен быть вызываемым и принимать один аргумент. То, когда результат становится готовым callback , применено к нему, это - то, если неудавшееся требование, в этом случае error_callback не применен вместо этого. Если задан параметр error_callback , то он должен быть вызываемым и принимать один аргумент. Если целевая функция терпит неудачу, то error_callback называют за исключением сущность. Обратные вызовы должны быть завершены немедленно, поскольку в противном случае поток, обрабатывающая результаты, будет заблокирована. imap ( func , iterable [ , chunksize ] ) ¶ Более ленивый вариант map() . Аргумент chunksize совпадает с аргументом используемый методом map() . Очень долго iterables использование большого значение для chunksize может заставить работу закончить гораздо быстрее, чем использование дефолта значение 1 . Также если chunksize является 1 , то метод next() итератора возвращенный методом imap() имеет необязательный параметр timeout : next(timeout) поднимет multiprocessing.TimeoutError , если результат не может быть возвращенный в течение timeout секунд. imap_unordered ( func , iterable [ , chunksize ] ) ¶ То же как imap() за исключением того, что заказ результатов возвращенный iterator нужно считать произвольным. (Только при наличии только одного рабочего процесса порядок гарантирован как «правильный». starmap ( func , iterable [ , chunksize ] ) ¶ Как map() за исключением того, что элементы iterable , как ожидают, будут iterables, которые распакованы как аргументы. Следовательно iterable [(1,2), (3, 4)] приводит к [func(1,2), func(3,4)] . Добавлено в версии 3.3. starmap_async ( func , iterable [ , chunksize [ , callback [ , error_callback ] ] ] ) ¶ Комбинация starmap() и map_async() , которая итерирует по iterable итераблей и вызывает func с итераблями распакованными. Возвращает объект результата. Добавлено в версии 3.3. close ( ) ¶ Запрещает отправку дополнительных задач в пул. После завершения всех задач рабочие процессы завершаются. terminate ( ) ¶ Немедленная остановка рабочих процессов без завершения незавершенной работы. То, когда объект бассейна - мусор, собралось, terminate() немедленно назовут. join ( ) ¶ Дождитесь завершения рабочих процессов. Перед использованием close() необходимо вызвать terminate() или join() . class multiprocessing.pool. AsyncResult ¶ Класс результата возвращенный по Pool.apply_async() и Pool.map_async() . get ( [ timeout ] ) ¶ Возвращает результат при его поступлении. Если timeout не является None и результат не поступает в течение timeout секунд, то multiprocessing.TimeoutError поднимается. Если удаленное требование подняло исключение тогда, что исключение будет повторно поднято get() . wait ( [ timeout ] ) ¶ Подождите, пока результат будет доступен, или до истечения timeout секунд. ready ( ) ¶ Возвращает, завершен ли вызов. successful ( ) ¶ Возвращает, выполнен ли вызов без возникновения исключения. Поднимет ValueError , если результат не готов. В следующем примере показано использование пула: from multiprocessing import Pool import time def f ( x ): return x * x if __name__ == '__main__' : with Pool ( processes = 4 ) as pool : # запустить 4 процесса воркера result = pool . apply_async ( f , ( 10 ,)) # асинхронно вычислить "f(10)" в одном процессе print ( result . get ( timeout = 1 )) # печатает "100", если только ваш компьютер не работает *очень* медленно print ( pool . map ( f , range ( 10 ))) # печать "[0, 1, 4,..., 81]" it = pool . imap ( f , range ( 10 )) print ( next ( it )) # печать "0" print ( next ( it )) # печать "1" print ( it . next ( timeout = 1 )) # печать "4" если ваш компьютер не *очень* медленный result = pool . apply_async ( time . sleep , ( 10 ,)) print ( result . get ( timeout = 1 )) # поднять multiprocessing.TimeoutError Слушатели и клиенты ¶ Обычно сообщение, проходящее между процессами, сделано, используя очереди, или при помощи Connection возражает возвращенный Pipe() . Однако модуль multiprocessing.connection обеспечивает некоторую гибкость. Он в основном дает высокоуровневый ориентированный на сообщения API для работы с сокеты или Windows с именем пайпы. У этого также есть поддержка digest authentication , используя модуль hmac , и опроса многочисленных связей одновременно. multiprocessing.connection. deliver_challenge ( connection , authkey ) ¶ Отправка случайно сгенерированного сообщения на другой конец соединения и ожидание ответа. Если ответ соответствует дайджесту сообщения с использованием клавиши authkey , то приветственное сообщение отправляется на другой конец соединения. В противном случае поднимается AuthenticationError . multiprocessing.connection. answer_challenge ( connection , authkey ) ¶ Получение сообщения, вычисление дайджеста сообщения с использованием authkey в качестве ключа, а затем отправка дайджеста обратно. Если приветственное сообщение не получено, возникает сообщение AuthenticationError . multiprocessing.connection. Client ( address [ , family [ , authkey ] ] ) ¶ Попытка установить соединение с прослушивателем, который использует адрес address , возвращая Connection . Тип соединения определяется аргументом family , но обычно его можно опустить, поскольку его обычно можно вывести из формата address . (См. Форматы адреса ) Если authkey задан, а не None, он должен быть байтом строка и будет используемый в качестве секретного ключа для вызова аутентификации на основе HMAC. Аутентификация не выполняется, если authkey является None. AuthenticationError возникает в случае сбоя аутентификации. См. Ключи аутентификации . class multiprocessing.connection. Listener ( [ address [ , family [ , backlog [ , authkey ] ] ] ] ) ¶ Обертка для связанной сокет или Windows с именем пайп, которая «слушает» подключения. address - адрес, который должен быть используемый связанным сокет или именованным пайп объекта прослушивателя. Примечание Если адрес „0.0.0.0“ будет используемый, то адрес не будет соединяемой конечной точкой на Windows. Если требуется соединяемая конечная точка, следует использовать „127.0.0.1“. family - тип используемого сокет (или именованного пайп). Это может быть один из строки 'AF_INET' (для TCP сокет), 'AF_UNIX' (для домена Unix сокет) или 'AF_PIPE' (для Windows с именем пайп). Из них только первый гарантированно доступен. Если family None , то семейство выводится из формата address . Если address также является None , то выбирается значение по умолчанию. Это семейство по умолчанию считается самым быстрым из доступных. См. Форматы адреса . Обратите внимание, что если family является 'AF_UNIX' и адрес None , то сокет будет создан в частном временном каталоге, созданном с помощью tempfile.mkstemp() . Если объект прослушивателя использует сокет, то backlog (по умолчанию 1) передается методу listen() сокет после его привязки. Если authkey задан, а не None, он должен быть байтом строка и будет используемый в качестве секретного ключа для вызова аутентификации на основе HMAC. Аутентификация не выполняется, если authkey является None. AuthenticationError возникает в случае сбоя аутентификации. См. Ключи аутентификации . accept ( ) ¶ Принять подключение на связанном сокете или именованный пайп объекта слушателя и возвращает объект Connection . Если идентификация предпринята и терпит неудачу, то поднимается AuthenticationError . close ( ) ¶ Закрыть связанный сокет или именованный пайп объекта слушателя. Это вызывается автоматически при сборе мусора прослушивателя. Однако желательно называть его явно. Объекты прослушивателя имеют следующие свойства только для чтения: address ¶ Адрес, используемый объектом Listener. last_accepted ¶ Адрес, с которого пришло последнее принятое соединение. Если это недоступно, то это None . Добавлено в версии 3.3: Объекты прослушивателя теперь поддерживают протокол управления контекст - см. раздел Типы менеджера контекста . __enter__() возвращает объект прослушивателя, а __exit__() вызывает close() . multiprocessing.connection. wait ( object_list , timeout=None ) ¶ Подождите, пока объект в object_list будет готов. Возвращает список тех объектов в object_list , которые готовы. Если timeout является float, то вызов блокируется максимум на столько секунд. Если timeout будет None тогда, то он заблокирует в течение неограниченного периода. Отрицательное время ожидания эквивалентно нулевому времени ожидания. Как для Unix, так и для Windows объект может отображаться в object_list , если это так читаемый объект Connection ; подключенный и читаемый объект socket.socket ; или sentinel атрибут объекта Process . Соединение или объект сокет готов, когда имеются данные, доступные для чтения из него, или другой конец закрыт. Unix : wait(object_list, timeout) почти эквивалентный select.select(object_list, [], [], timeout) . Разница в том, что, если select.select() прерывается сигналом, он может поднять OSError с числом ошибок EINTR , тогда как wait() не будет. Windows : Элемент в object_list должен или быть целочисленным обработчиком, который ожидает (waitable) (согласно определению используемый документацией функции Win32 WaitForMultipleObjects() ), или это может быть объект с методом fileno() , с каким возвращает ручка сокет или пайп обращаются. (Обратите внимание, что дескрипторы пайпа и сокет не являются дескрипторами ожидания. Добавлено в версии 3.3. Примеры Следующий код сервера создает слушателя, который использует 'secret password' в качестве ключа идентификации. Затем он ожидает подключения и передает некоторые данные клиенту: from multiprocessing.connection import Listener from array import array address = ( 'localhost' , 6000 ) # семейство выведено как 'AF_INET' with Listener ( address , authkey = b 'secret password' ) as listener : with listener . accept () as conn : print ( 'connection accepted from' , listener . last_accepted ) conn . send ([ 2.25 , None , 'junk' , float ]) conn . send_bytes ( b 'hello' ) conn . send_bytes ( array ( 'i' , [ 42 , 1729 ])) Следующая код подключается к серверу и получает некоторые данные от сервера: from multiprocessing.connection import Client from array import array address = ( 'localhost' , 6000 ) with Client ( address , authkey = b 'secret password' ) as conn : print ( conn . recv ()) # => [2.25, None, 'junk', float] print ( conn . recv_bytes ()) # => 'hello' arr = array ( 'i' , [ 0 , 0 , 0 , 0 , 0 ]) print ( conn . recv_bytes_into ( arr )) # => 8 print ( arr ) # => array('i', [42, 1729, 0, 0, 0]) Следующая код использует wait() для ожидания сообщений от нескольких процессов одновременно: import time , random from multiprocessing import Process , Pipe , current_process from multiprocessing.connection import wait def foo ( w ): for i in range ( 10 ): w . send (( i , current_process () . name )) w . close () if __name__ == '__main__' : readers = [] for i in range ( 4 ): r , w = Pipe ( duplex = False ) readers . append ( r ) p = Process ( target = foo , args = ( w ,)) p . start () # Мы закрываем записываемый конец пайп, чтобы убедиться, что p является # единственным процессом, который владеет дескриптором для него. Это гарантирует, # что когда p закроет свой дескриптор для записываемого конца, wait() # быстро сообщит о читаемом конце как о прочитанном. w . close () while readers : for r in wait ( readers ): try : msg = r . recv () except EOFError : readers . remove ( r ) else : print ( msg ) Форматы адреса ¶ Адрес 'AF_INET' - кортеж формы (hostname, port) , где hostname - строка, а port - целое число. Адрес 'AF_UNIX' - это строка, представляющий имя файла в файловой системе. Адрес 'AF_PIPE' представляет собой строку вида r'\\.\pipe{PipeName}' . Чтобы использовать Client() для подключения к именованному каналу на удаленном компьютере с именем ServerName , вместо этого следует использовать адрес формы r'\ ServerName \pipe{PipeName}' . Обратите внимание, что любая строка, начинающаяся с двух обратных косых черт, по умолчанию принимается как 'AF_PIPE' адрес, а не 'AF_UNIX' адрес. Ключи аутентификации ¶ Когда каждый использует Connection.recv , полученными данными является автоматически unpickled. К сожалению, отмена извлечения данных из ненадежного источника является угрозой безопасности. Поэтому Listener и Client() используйте модуль hmac для обеспечения дайджест-аутентификации. Ключ аутентификации - это байт строка, который можно рассматривать как пароль: после установления соединения оба конца потребуют подтверждения того, что другой знает ключ аутентификации. (Демонстрирующий то, что оба конца используют тот же ключ, делает не , включают отправку ключа по связи.) Если идентификацию запрошенный, но никакой ключ идентификации не определен тогда, возвращает значение current_process().authkey - используемый (см. Process ). Этот значение будет автоматически унаследован любым объектом Process , что текущий процесс создает. Это означает, что (по умолчанию) все процессы многопроцессорной программы будут совместно использовать один ключ аутентификации, который может быть используемый при установке соединений между собой. Подходящие ключи аутентификации также могут быть сгенерированы с использованием os.urandom() . Логирование ¶ Доступна некоторая поддержка логирование. Однако следует отметить, что пакет logging не использует общие блокировки процессов, что позволяет (в зависимости от типа обработчик) смешивать сообщения из различных процессов. multiprocessing. get_logger ( ) ¶ Возвращает логгер используемый по multiprocessing . При необходимости будет создан новый. При первом создании логгер имеет уровень logging.NOTSET и не имеет обработчик по умолчанию. Сообщения, отправляемые этому логгер, по умолчанию не распространяются на корневой логгер. Обратите внимание, что в Windows дочерние процессы наследуют только уровень логгер родительского процесса - любая другая настройка логгер не наследуется. multiprocessing. log_to_stderr ( ) ¶ Эта функция выполняет вызов get_logger() , но в дополнение к возвращению логгер, созданного get_logger, она добавляет обработчик, который отправляет вывод в sys.stderr , используя формат '[%(levelname)s/%(processName)s] %(message)s' . Ниже приведен пример сеанса с включенной функцией логирование: >>> >>> import multiprocessing , logging >>> logger = multiprocessing . log_to_stderr () >>> logger . setLevel ( logging . INFO ) >>> logger . warning ( 'doomed' ) [WARNING/MainProcess] doomed >>> m = multiprocessing . Manager () [INFO/SyncManager-...] child process calling self.run() [INFO/SyncManager-...] created temp directory /.../pymp-... [INFO/SyncManager-...] manager serving at '/.../listener-...' >>> del m [INFO/MainProcess] sending shutdown message to manager [INFO/SyncManager-...] manager exiting with exitcode 0 Полную таблицу уровней логирование см. в модуле logging . Модуль multiprocessing.dummy ¶ multiprocessing.dummy копирует API multiprocessing , но является не более чем оболочкой для модуля threading . В частности, функция Pool , предоставляемая multiprocessing.dummy , возвращает экземпляр ThreadPool , который является подклассом Pool , который поддерживает все те же вызовы методов, но использует пул рабочих потоков, а не рабочих процессов. class multiprocessing.pool. ThreadPool ( [ processes [ , initializer [ , initargs ] ] ] ) ¶ Объект пула потоков, который управляет пулом рабочих потоков, которым могут быть отправлены задания. Экземпляры ThreadPool полностью совместимы по интерфейсу с экземплярами Pool , и их ресурсами также необходимо правильно управлять, используя пул в качестве диспетчера контекста или вызывая close() и terminate() вручную. processes - количество используемых рабочих потоков. Если processes - None , то используется номер, возвращенный os.cpu_count() . Если initializer не None , то каждый рабочий процесс при запуске будет вызывать initializer(*initargs) . В отличие от Pool , maxtasksperchild и context не могут быть предоставлены. Примечание ThreadPool имеет тот же интерфейс, что и Pool , который разработан на основе пула процессов и предшествует введению модуля concurrent.futures . Таким образом, он наследует некоторые операции, которые не имеют смысла для пула, поддерживаемого потоками, и имеет свой собственный тип для представления состояния асинхронных заданий, AsyncResult , который не понимается никакими другими библиотеками. Пользователям обычно следует использовать concurrent.futures.ThreadPoolExecutor , который имеет более простой интерфейс, изначально спроектированный для потоков, и который возвращает экземпляры concurrent.futures.Future , совместимые со многими другими библиотеками, включая asyncio . Программирование рекомендаций ¶ Существуют определенные руководящие принципы и идиомы, которых следует придерживаться при использовании multiprocessing . Все методы начала ¶ Следующее относится ко всем методам запуска. Избегайте разделенного состояние Насколько это возможно, следует стараться избегать переноса больших объемов данных между процессами. Вероятно, лучше всего использовать очереди или пайпы для обмена данными между процессами, чем использовать примитивы синхронизации более низкого уровня. Picklability Убедитесь в том, что аргументы для методов прокси-серверов доступны. Безопасность потоков прокси Не используйте прокси-объект из нескольких поток, если вы не защитите его с помощью блокировки. (Никогда нет проблемы с различными процессами, используя прокси same .) Присоединение к процессам зомби В Unix, когда процесс заканчивается, но не был присоединен, он становится зомби. Никогда не должно быть очень многих, потому что каждый раз новый процесс начинается (или active_children() называют), все законченные процессы, к которым еще не присоединились, будет присоединен. Кроме того, вызов Process.is_alive завершенного процесса присоединится к процессу. Тем не менее, это, вероятно, хорошая практика, чтобы явно присоединиться ко всем процессам, которые вы начинаете. Лучше наследовать, чем pickle/unpickle При использовании методов запуска spawn или forkserver многие типы из multiprocessing должны быть подбираемыми, чтобы их могли использовать дочерние процессы. Однако обычно следует избегать отправки общих объектов другим процессам с использованием пайпов или очередей. Вместо этого следует упорядочить программу так, чтобы процесс, которому необходим доступ к общему ресурсу, созданному в другом месте, мог наследовать его от предшествующего процесса. Постарайтесь не заканчивать процессы Используя метод Process.terminate , чтобы остановить процесс склонно заставить любые общие ресурсы (такие как замки, семафоры, пайпы и очереди) в настоящее время являющийся используемый процессом становиться сломанными или недоступными к другим процессам. Поэтому, вероятно, лучше только рассмотреть использование Process.terminate на процессах, которые никогда не используют общих ресурсов. Объединение процессов, использующих очереди Следует иметь в виду, что процесс, поставивший элементы в очередь, будет ждать завершения до тех пор, пока все буферизированные элементы не будут поданы «питателем» поток в нижележащий пайп. (Дочерний процесс может вызвать метод Queue.cancel_join_thread очереди, чтобы избежать такого поведения. Это означает, что при каждом использовании очереди необходимо убедиться, что все элементы, помещенные в очередь, будут удалены до присоединения процесса. В противном случае вы не можете быть уверены, что процессы, поставившие элементы в очередь, завершатся. Также следует помнить, что недемонические процессы будут присоединяться автоматически. Примером взаимоблокировки является следующее: from multiprocessing import Process , Queue def f ( q ): q . put ( 'X' * 1000000 ) if __name__ == '__main__' : queue = Queue () p = Process ( target = f , args = ( queue ,)) p . start () p . join () # это мертвая блокировка obj = queue . get () Фиксация здесь должна была бы обменять последние две линии (или просто удалить линию p.join() ). Явная передача ресурсов дочерним процессам На Unix, используя метод начала fork , дочерний процесс может использовать общий ресурс, созданный в родительском процессе, используя глобальный ресурс. Однако лучше передать объект в качестве аргумента конструктору для дочернего процесса. Кроме обеспечения совместимости код (потенциально) с Windows и другими методами запуска, это также гарантирует, что до тех пор, пока дочерний процесс еще жив, объект не будет мусором собран в родительском процессе. Это может быть важно, если какой-либо ресурс освобождается при сборе мусора объекта в родительском процессе. Таким образом для сущность: from multiprocessing import Process , Lock def f (): ... сделать что - то используя "lock" ... if __name__ == '__main__' : lock = Lock () for i in range ( 10 ): Process ( target = f ) . start () следует переписать как: from multiprocessing import Process , Lock def f ( l ): ... сделать что - нибудь , используя "l" ... if __name__ == '__main__' : lock = Lock () for i in range ( 10 ): Process ( target = f , args = ( lock ,)) . start () Остерегайтесь замены sys.stdin на «файл, как объект» multiprocessing изначально безоговорочно вызвается: os . close ( sys . stdin . fileno ()) в методе multiprocessing.Process._bootstrap() — это привело к проблемам с процессами в процессах. Это было изменено на: sys . stdin . close () sys . stdin = open ( os . open ( os . devnull , os . O_RDONLY ), closefd = False ) Который решает основную проблему процессов, сталкивающихся друг с другом приводящим к плохой ошибке файла дескриптор, но вводит потенциальную опасность для заявлений, которые заменяют sys.stdin() «подобным файлу объектом» с буферизующей продукцией. Эта опасность заключается в том, что если несколько процессов вызывают close() на этом файловом объекте, это может привести к тому, что одни и те же данные будут очищены на объекте несколько раз, что приведет к повреждению. Если вы пишете подобный файлу объект и осуществляете ваш собственный кэширование, вы можете сделать его безопасным от вилки, храня pid каждый раз, когда вы прилагаете к кэш и отказу от кэш, когда pid изменяется. Например: @property def cache ( self ): pid = os . getpid () if pid != self . _pid : self . _pid = pid self . _cache = [] return self . _cache Дополнительные сведения см. в разделах bpo-5155 , bpo-5313 и bpo-5331 Методы запуска spawn и forkserver ¶ Есть некоторые дополнительное ограничение, которые не относятся к методу начала fork . Больше picklability Убедитесь, что все аргументы для Process.__init__() доступны. Кроме того, если вы, подкласс Process тогда удостоверяется, что сущности будет picklable, когда метод Process.start назовут. Глобальные переменные Принять во внимание, что, если пробег код в дочернем процессе пытается получить доступ к глобальной переменной, то значение он видит (если таковые имеются) может не совпасть с значение в родительском процессе в то время, когда вызван Process.start . Однако глобальные переменные, являющиеся только константами уровня модуля, не вызывают проблем. Безопасный импорт основного модуля Удостоверьтесь, что главный модуль может быть безопасно импортирован новым Python интерпретатор, не вызывая непреднамеренные побочные эффекты (такой старт нового процесса). Например, использование метода начала spawn или forkserver , управляющего следующим модулем, потерпело бы неудачу с RuntimeError : from multiprocessing import Process def foo (): print ( 'hello' ) p = Process ( target = foo ) p . start () Вместо этого следует защитить «точку входа» программы, используя if __name__ == '__main__': следующим образом: from multiprocessing import Process , freeze_support , set_start_method def foo (): print ( 'hello' ) if __name__ == '__main__' : freeze_support () set_start_method ( 'spawn' ) p = Process ( target = foo ) p . start () (Строка freeze_support() может быть опущена, если программа будет запущена нормально, а не заморожена. Это позволяет недавно порожденному Python интерпретатор безопасно импортировать модуль и затем управлять функцией foo() модуля. Аналогичные ограничения применяются в случае создания пула или менеджера в главном модуле. Примеры ¶ Демонстрация создания и использования настраиваемых менеджеров и прокси: from multiprocessing import freeze_support from multiprocessing.managers import BaseManager , BaseProxy import operator ## class Foo : def f ( self ): print ( 'you called Foo.f()' ) def g ( self ): print ( 'you called Foo.g()' ) def _h ( self ): print ( 'you called Foo._h()' ) # A simple generator function def baz (): for i in range ( 10 ): yield i * i # Proxy type for generator objects class GeneratorProxy ( BaseProxy ): _exposed_ = [ '__next__' ] def __iter__ ( self ): return self def __next__ ( self ): return self . _callmethod ( '__next__' ) # Function to return the operator module def get_operator_module (): return operator ## class MyManager ( BaseManager ): pass # register the Foo class; make `f()` and `g()` accessible via proxy MyManager . register ( 'Foo1' , Foo ) # register the Foo class; make `g()` and `_h()` accessible via proxy MyManager . register ( 'Foo2' , Foo , exposed = ( 'g' , '_h' )) # register the generator function baz; use `GeneratorProxy` to make proxies MyManager . register ( 'baz' , baz , proxytype = GeneratorProxy ) # register get_operator_module(); make public functions accessible via proxy MyManager . register ( 'operator' , get_operator_module ) ## def test (): manager = MyManager () manager . start () print ( '-' * 20 ) f1 = manager . Foo1 () f1 . f () f1 . g () assert not hasattr ( f1 , '_h' ) assert sorted ( f1 . _exposed_ ) == sorted ([ 'f' , 'g' ]) print ( '-' * 20 ) f2 = manager . Foo2 () f2 . g () f2 . _h () assert not hasattr ( f2 , 'f' ) assert sorted ( f2 . _exposed_ ) == sorted ([ 'g' , '_h' ]) print ( '-' * 20 ) it = manager . baz () for i in it : print ( '< %d >' % i , end = ' ' ) print () print ( '-' * 20 ) op = manager . operator () print ( 'op.add(23, 45) =' , op . add ( 23 , 45 )) print ( 'op.pow(2, 94) =' , op . pow ( 2 , 94 )) print ( 'op._exposed_ =' , op . _exposed_ ) ## if __name__ == '__main__' : freeze_support () test () Использование Pool : import multiprocessing import time import random import sys # # Functions used by test code # def calculate ( func , args ): result = func ( * args ) return ' %s says that %s%s = %s ' % ( multiprocessing . current_process () . name , func . __name__ , args , result ) def calculatestar ( args ): return calculate ( * args ) def mul ( a , b ): time . sleep ( 0.5 * random . random ()) return a * b def plus ( a , b ): time . sleep ( 0.5 * random . random ()) return a + b def f ( x ): return 1.0 / ( x - 5.0 ) def pow3 ( x ): return x ** 3 def noop ( x ): pass # # Test code # def test (): PROCESSES = 4 print ( 'Creating pool with %d processes \n ' % PROCESSES ) with multiprocessing . Pool ( PROCESSES ) as pool : # # Tests # TASKS = [( mul , ( i , 7 )) for i in range ( 10 )] + \ [( plus , ( i , 8 )) for i in range ( 10 )] results = [ pool . apply_async ( calculate , t ) for t in TASKS ] imap_it = pool . imap ( calculatestar , TASKS ) imap_unordered_it = pool . imap_unordered ( calculatestar , TASKS ) print ( 'Ordered results using pool.apply_async():' ) for r in results : print ( ' \t ' , r . get ()) print () print ( 'Ordered results using pool.imap():' ) for x in imap_it : print ( ' \t ' , x ) print () print ( 'Unordered results using pool.imap_unordered():' ) for x in imap_unordered_it : print ( ' \t ' , x ) print () print ( 'Ordered results using pool.map() --- will block till complete:' ) for x in pool . map ( calculatestar , TASKS ): print ( ' \t ' , x ) print () # # Test error handling # print ( 'Testing error handling:' ) try : print ( pool . apply ( f , ( 5 ,))) except ZeroDivisionError : print ( ' \t Got ZeroDivisionError as expected from pool.apply()' ) else : raise AssertionError ( 'expected ZeroDivisionError' ) try : print ( pool . map ( f , list ( range ( 10 )))) except ZeroDivisionError : print ( ' \t Got ZeroDivisionError as expected from pool.map()' ) else : raise AssertionError ( 'expected ZeroDivisionError' ) try : print ( list ( pool . imap ( f , list ( range ( 10 ))))) except ZeroDivisionError : print ( ' \t Got ZeroDivisionError as expected from list(pool.imap())' ) else : raise AssertionError ( 'expected ZeroDivisionError' ) it = pool . imap ( f , list ( range ( 10 ))) for i in range ( 10 ): try : x = next ( it ) except ZeroDivisionError : if i == 5 : pass except StopIteration : break else : if i == 5 : raise AssertionError ( 'expected ZeroDivisionError' ) assert i == 9 print ( ' \t Got ZeroDivisionError as expected from IMapIterator.next()' ) print () # # Testing timeouts # print ( 'Testing ApplyResult.get() with timeout:' , end = ' ' ) res = pool . apply_async ( calculate , TASKS [ 0 ]) while 1 : sys . stdout . flush () try : sys . stdout . write ( ' \n\t %s ' % res . get ( 0.02 )) break except multiprocessing . TimeoutError : sys . stdout . write ( '.' ) print () print () print ( 'Testing IMapIterator.next() with timeout:' , end = ' ' ) it = pool . imap ( calculatestar , TASKS ) while 1 : sys . stdout . flush () try : sys . stdout . write ( ' \n\t %s ' % it . next ( 0.02 )) except StopIteration : break except multiprocessing . TimeoutError : sys . stdout . write ( '.' ) print () print () if __name__ == '__main__' : multiprocessing . freeze_support () test () Пример использования очередей для подачи задач в коллекцию рабочих процессов и сбора результатов:
Markdown
### Навигация - [указатель](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/genindex.html "Алфавитный указатель") - [модули](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/py-modindex.html "Содержание модулей Python") \| - [вперёд](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.shared_memory.html "multiprocessing.shared_memory — Предоставляет общую память для прямого доступа между процессами") \| - [назад](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html "threading — Потоковый параллелизм") \| - ![](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/_static/py.png) - [Python](https://digitology.tech/) » - [3\.8.8 Документация](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/index.html) » - [Стандартная библиотека Python](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/index.html) » - [Конкурентное выполнение](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/concurrency.html) » - \| [Поддержать первод](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/donate.html) # [`multiprocessing`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing "multiprocessing: Процессный параллелизм.") — Процессный параллелизм[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing "Ссылка на этот заголовок") **Исходный код:** [Lib/multiprocessing/](https://github.com/python/cpython/tree/3.8/Lib/multiprocessing/) *** ## Введение[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id1 "Ссылка на этот заголовок") [`multiprocessing`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing "multiprocessing: Процессный параллелизм.") - это пакет, который поддерживает порождение процессов с использованием API, похожим на модуль [`threading`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#module-threading "threading: Потоковый параллелизм."). Пакет [`multiprocessing`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing "multiprocessing: Процессный параллелизм.") предлагает как локальный, так и удаленный параллелизм, эффективно обходя [Глобальную блокировку интерпретатора](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/glossary.html#term-52) с использованием подпроцессов вместо потоков. Также модуль [`multiprocessing`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing "multiprocessing: Процессный параллелизм.") позволяет программисту полностью использовать несколько процессоров на данном компьютере. Работает как на Unix, так и на Windows. Модуль [`multiprocessing`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing "multiprocessing: Процессный параллелизм.") также вводит API, которые не имеет аналогов в модуле [`threading`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#module-threading "threading: Потоковый параллелизм."). Ярким примером этого является объект [`Pool`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool "multiprocessing.pool.Pool"), который предлагает удобное средство параллелирования выполнения функции по множеству входных значениц, распределения входных данных по процессам (параллелизм данных). Следующий пример демонстрирует обычную практику определения таких функций в модуле, чтобы дочерние процессы могли успешно импортировать этот модуль. Этот базовый пример параллелизма данных с использованием [`Pool`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool "multiprocessing.pool.Pool"): ``` from multiprocessing import Pool def f(x): return x*x if __name__ == '__main__': with Pool(5) as p: print(p.map(f, [1, 2, 3])) ``` будет напечатано в стандартный вывод: ``` [1, 4, 9] ``` ### Класс [`Process`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process "multiprocessing.Process")[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#process "Ссылка на этот заголовок") В [`multiprocessing`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing "multiprocessing: Процессный параллелизм.") процессы порождаются созданием объекта [`Process`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process "multiprocessing.Process"), а затем вызовом его метода [`start()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.start "multiprocessing.Process.start"). [`Process`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process "multiprocessing.Process") следует API [`threading.Thread`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.Thread "threading.Thread"). Тривиальный пример многопроцессорной программы: ``` from multiprocessing import Process def f(name): print('hello', name) if __name__ == '__main__': p = Process(target=f, args=('bob',)) p.start() p.join() ``` Ниже приведен развернутый пример, показывающий соответствующие идентификаторы отдельных процессов: ``` from multiprocessing import Process import os def info(title): print(title) print('module name:', __name__) print('parent process:', os.getppid()) print('process id:', os.getpid()) def f(name): info('function f') print('hello', name) if __name__ == '__main__': info('main line') p = Process(target=f, args=('bob',)) p.start() p.join() ``` Объяснение причины необходимости `if __name__ == '__main__'` части см. в разделе [Программирование рекомендаций](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-programming). ### Контексты и методы запуска[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id2 "Ссылка на этот заголовок") В зависимости от платформы, [`multiprocessing`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing "multiprocessing: Процессный параллелизм.") поддерживает три способа запуска процесса. Далее перечислены *методы запуска*. > *spawn* > > Родительский процесс запускает новый процесс интерпретатора Python. Дочерний процесс унаследует только те ресурсы, которые необходимы для выполнения метода [`run()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.run "multiprocessing.Process.run") объекта процесса. В частности, ненужные файловые дескрипторы и дескрипторы родительского процесса не будут унаследованы. Запуск процесса с использованием этого метода довольно медленный по сравнению с использованием *fork* или *forkserver*. > > Доступно в Unix и Windows. Значение по умолчанию для Windows и macOS. > > *fork* > > Родительский процесс использует [`os.fork()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/os.html#os.fork "os.fork") для форсирования Python интерпретатор. Дочерний процесс, когда он начинается, фактически идентичен родительскому процессу. Все ресурсы родителя наследуются дочерним процессом. Следует отметить, что безопасная форсировка многопоточного процесса является проблематичной. > > Доступно только в Unix. Значение по умолчанию в Unix. > > *forkserver* > > Когда программа начинает и выбирает метод начала *forkserver*, процесс сервера, начат. С этого момента всякий раз, когда требуется новый процесс, родительский процесс подключается к серверу и запрашивает, чтобы он форсировал новый процесс. Процесс сервера вилки является однопотоковым, поэтому он безопасен для использования [`os.fork()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/os.html#os.fork "os.fork"). Ненужные ресурсы не наследуются. > > Доступный на платформах Unix, которые поддерживают мимолетный файл дескрипторы по Unix пайпы. Изменено в версии 3.8: На macOS метод начала *spawn* - теперь дефолт. Метод запуска *fork* следует считать небезопасным, поскольку он может привести к сбоям подпроцессы. См. [bpo-33725](https://bugs.python.org/issue33725). Изменено в версии 3.4: *spawn* добавлены на всех платформах unix и *forkserver* добавлены для некоторых платформ unix. Дочерние процессы больше не наследуют все унаследованные родительские дескрипторы в Windows. В Unix с помощью методов запуска *spawn* или *forkserver* также запускается процесс *resource tracker*, который отслеживает несвязанные именованные системные ресурсы (такие как именованные семафоры или [`SharedMemory`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.shared_memory.html#multiprocessing.shared_memory.SharedMemory "multiprocessing.shared_memory.SharedMemory") объекты), созданные процессами программы. После завершения всех процессов средство отслеживания ресурсов отменяет связь с любым оставшимся отслеживаемым объектом. Обычно их не должно быть, но если какой-либо процесс был убит сигналом, то может возникнуть некоторая «утечка» ресурсов. (Ни просочившиеся семафоры, ни сегменты общей памяти не будут автоматически отключены до следующей перезагрузки. Это проблематично для обоих объектов, поскольку система допускает только ограниченное количество именованных семафоров, а сегменты совместно используемой памяти занимают некоторое место в основной памяти.) Для выбора метода запуска используется [`set_start_method()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.set_start_method "multiprocessing.set_start_method") в `if __name__ == '__main__'` клаузула основного модуля. Например: ``` import multiprocessing as mp def foo(q): q.put('hello') if __name__ == '__main__': mp.set_start_method('spawn') q = mp.Queue() p = mp.Process(target=foo, args=(q,)) p.start() print(q.get()) p.join() ``` [`set_start_method()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.set_start_method "multiprocessing.set_start_method") не должны быть используемый более одного раза в программе. Кроме того, можно использовать [`get_context()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.get_context "multiprocessing.get_context") для получения объекта контекст. Объекты контекста имеют тот же API, что и модуль многопроцессорной обработки, и позволяют использовать несколько методов запуска в одной программе: ``` import multiprocessing as mp def foo(q): q.put('hello') if __name__ == '__main__': ctx = mp.get_context('spawn') q = ctx.Queue() p = ctx.Process(target=foo, args=(q,)) p.start() print(q.get()) p.join() ``` Обратите внимание, что объекты, связанные с одним контекст, могут быть несовместимы с процессами для другого контекст. В частности, блокировки, созданные с помощью *fork* контекст, не могут быть переданы процессам, запущенным с помощью методов запуска *spawn* или *forkserver*. Библиотека, которая хочет использовать конкретный метод запуска, должна, вероятно, использовать [`get_context()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.get_context "multiprocessing.get_context"), чтобы избежать вмешательства в выбор пользователя библиотеки. Предупреждение Стартовые методы `'spawn'` и `'forkserver'` в настоящее время не могут быть используемый с «замороженными» исполняемыми файлами (т.е. двоичными файлами, создаваемыми пакетами, такими как **PyInstaller** and **cx\_Freeze**) в Unix. Стартовый метод `'fork'` работает. ### Обмен объектами между процессами[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id3 "Ссылка на этот заголовок") [`multiprocessing`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing "multiprocessing: Процессный параллелизм.") поддерживает два типа каналов связи между процессами: **Очереди** > Класс [`Queue`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue "multiprocessing.Queue") является близким клоном [`queue.Queue`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/queue.html#queue.Queue "queue.Queue"). Например: > ``` > from multiprocessing import Process, Queue def f(q): q.put([42, None, 'hello']) if __name__ == '__main__': q = Queue() p = Process(target=f, args=(q,)) p.start() print(q.get()) # распечатает "[42, None, 'hello']" p.join() > ``` > Очереди поток и безопасны для обработки. **Пайпы** > [`Pipe()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Pipe "multiprocessing.Pipe") функционируют возвращает пара объектов связи, связанных пайп, который по умолчанию является (двухсторонним) дуплексом. Например: > ``` > from multiprocessing import Process, Pipe def f(conn): conn.send([42, None, 'hello']) conn.close() if __name__ == '__main__': parent_conn, child_conn = Pipe() p = Process(target=f, args=(child_conn,)) p.start() print(parent_conn.recv()) # распечатает "[42, None, 'hello']" p.join() > ``` > Два объекта соединения возвращенный [`Pipe()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Pipe "multiprocessing.Pipe") представляют два конца пайп. Каждый объект подключения имеет методы `send()` и `recv()` (среди прочих). Обратите внимание, что данные в пайп могут быть повреждены, если два процесса (или потоки) пытаются одновременно считать или записывать в *same* конец пайп. Конечно, нет риска коррупции от процессов, использующих разные концы пайп одновременно. ### Синхронизация между процессами[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id4 "Ссылка на этот заголовок") [`multiprocessing`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing "multiprocessing: Процессный параллелизм.") содержит эквиваленты всех примитивов синхронизации из [`threading`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#module-threading "threading: Потоковый параллелизм."). Для сущность можно использовать блокировку для обеспечения одновременной печати только одного процесса в стандартный вывод: ``` from multiprocessing import Process, Lock def f(l, i): l.acquire() try: print('hello world', i) finally: l.release() if __name__ == '__main__': lock = Lock() for num in range(10): Process(target=f, args=(lock, num)).start() ``` Без использования блокировки выходные данные различных процессов могут быть смешаны. ### Совместное использование состояние между процессами[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id5 "Ссылка на этот заголовок") Как упомянуто выше, когда выполнение параллельного программирования его является обычно лучшим избегать использования разделенного состояние в максимально возможной степени. Это особенно верно при использовании нескольких процессов. Однако, если вам действительно нужно использовать некоторые общие данные, то [`multiprocessing`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing "multiprocessing: Процессный параллелизм.") предоставляет пару способов сделать это. **Общая память** > Данные могут храниться в карте совместно используемой памяти с помощью [`Value`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Value "multiprocessing.Value") или [`Array`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Array "multiprocessing.Array"). Например, следующие код: > ``` > from multiprocessing import Process, Value, Array def f(n, a): n.value = 3.1415927 for i in range(len(a)): a[i] = -a[i] if __name__ == '__main__': num = Value('d', 0.0) arr = Array('i', range(10)) p = Process(target=f, args=(num, arr)) p.start() p.join() print(num.value) print(arr[:]) > ``` > напечатает: > ``` > 3.1415927 [0, -1, -2, -3, -4, -5, -6, -7, -8, -9] > ``` > Аргументы `'d'` и `'i'` используемый при создании `num` и `arr` являются типкодами вида используемый модулем [`array`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/array.html#module-array "array: Пространственно-эффективные массивы типизированных числовых значений."): `'d'` указывает двойную точность float и `'i'` обозначает целое число со знаком. Эти общие объекты будут процессом и потокобезопасной. > > Для большей гибкости в использовании совместно используемой памяти можно использовать модуль [`multiprocessing.sharedctypes`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing.sharedctypes "multiprocessing.sharedctypes: Аллоцировать объекты ctypes из общей памяти."), поддерживающий создание объектов произвольных ctypes, выделенных из совместно используемой памяти. **Серверный процесс** > Объект менеджера возвращенный `Manager()` управляет серверным процессом, который содержит объекты Python и позволяет другим процессам манипулировать ими с помощью прокси. > > Менеджер возвращенный `Manager()` поддержит типы [`list`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/stdtypes.html#list "list"), `dict`, [`Namespace`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.Namespace "multiprocessing.managers.Namespace"), [`Lock`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Lock "multiprocessing.Lock"), [`RLock`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.RLock "multiprocessing.RLock"), [`Semaphore`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Semaphore "multiprocessing.Semaphore"), [`BoundedSemaphore`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.BoundedSemaphore "multiprocessing.BoundedSemaphore"), [`Condition`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Condition "multiprocessing.Condition"), [`Event`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Event "multiprocessing.Event"), [`Barrier`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Barrier "multiprocessing.Barrier"), [`Queue`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue "multiprocessing.Queue"), [`Value`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Value "multiprocessing.Value") и [`Array`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Array "multiprocessing.Array"). Например,: > ``` > from multiprocessing import Process, Manager def f(d, l): d[1] = '1' d['2'] = 2 d[0.25] = None l.reverse() if __name__ == '__main__': with Manager() as manager: d = manager.dict() l = manager.list(range(10)) p = Process(target=f, args=(d, l)) p.start() p.join() print(d) print(l) > ``` > напечатает: > ``` > {0.25: None, 1: '1', '2': 2} [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] > ``` > Менеджеры серверных процессов более гибки, чем использование общих объектов памяти, поскольку они могут быть созданы для поддержки произвольных типов объектов. Кроме того, один менеджер может совместно использоваться процессами на разных компьютерах по сети. Однако они работают медленнее, чем совместно используемая память. ### Использование пула воркеров[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id6 "Ссылка на этот заголовок") Класс [`Pool`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool "multiprocessing.pool.Pool") представляет пул рабочих процессов. Он содержит методы, позволяющие выгружать задачи в рабочие процессы несколькими различными способами. Например: ``` from multiprocessing import Pool, TimeoutError import time import os def f(x): return x*x if __name__ == '__main__': # запуск 4 рабочих процессов with Pool(processes=4) as pool: # печать "[0, 1, 4,..., 81]" print(pool.map(f, range(10))) # печатать одинаковые числа в произвольном порядке for i in pool.imap_unordered(f, range(10)): print(i) # вычислить "f(20)" асинхронно res = pool.apply_async(f, (20,)) # запускается в *только* одном процессе print(res.get(timeout=1)) # печатает "400" # вычислить "os.getpid()" асинхронно res = pool.apply_async(os.getpid, ()) # запускается в *только* одном процессе print(res.get(timeout=1)) # печатает PID этого процесса # запуск нескольких оценок асинхронно *может* использовать больше процессов multiple_results = [pool.apply_async(os.getpid, ()) for i in range(4)] print([res.get(timeout=1) for res in multiple_results]) # уснуть одному рабочему на 10 секунд res = pool.apply_async(time.sleep, (10,)) try: print(res.get(timeout=1)) except TimeoutError: print("We lacked patience and got a multiprocessing.TimeoutError") print("For the moment, the pool remains available for more work") # выход из блока with с остановкой пула print("Now the pool is closed and no longer available") ``` Обратите внимание, что методы бассейна должны только когда-либо быть используемый процессом, который создал его. Примечание Функциональность этого пакета требует, чтобы модуль `__main__` был импортирован нижестоящими элементами. Это освещено в [Программирование рекомендаций](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-programming), однако здесь стоит указать. Это означает, что некоторые примеры, такие как примеры [`multiprocessing.pool.Pool`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool "multiprocessing.pool.Pool") не будут работать в интерактивном интерпретатор. Например: \>\>\> ``` >>> from multiprocessing import Pool >>> p = Pool(5) >>> def f(x): ... return x*x ... >>> with p: ... p.map(f, [1,2,3]) Process PoolWorker-1: Process PoolWorker-2: Process PoolWorker-3: Traceback (most recent call last): AttributeError: 'module' object has no attribute 'f' AttributeError: 'module' object has no attribute 'f' AttributeError: 'module' object has no attribute 'f' ``` (Если попробовать это, то на самом деле будет выведено три полных трейсбэки, перемежающихся полуслучайным образом, а затем, возможно, придется как-то остановить родительский процесс. ## Ссылка[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id7 "Ссылка на этот заголовок") Пакет [`multiprocessing`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing "multiprocessing: Процессный параллелизм.") в основном реплицирует API модуля [`threading`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#module-threading "threading: Потоковый параллелизм."). ### [`Process`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process "multiprocessing.Process") и исключения[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id8 "Ссылка на этот заголовок") *class* `multiprocessing.``Process`(*group=None*, *target=None*, *name=None*, *args=()*, *kwargs={}*, *\**, *daemon=None*)[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process "Ссылка на это определение") Объекты процесса представляют собой операцию, выполняемую в отдельном процессе. Класс [`Process`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process "multiprocessing.Process") имеет эквиваленты всех методов [`threading.Thread`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.Thread "threading.Thread"). Конструктор всегда должен вызываться с аргументами ключевой. *group* всегда должны быть `None`; он существует исключительно для совместимости с [`threading.Thread`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.Thread "threading.Thread"). *target* - вызываемый объект, вызываемый методом [`run()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.run "multiprocessing.Process.run"). По умолчанию он имеет значение `None`, то есть ничего не называется. *name* - имя процесса (более подробную информацию см. в разделе [`name`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.name "multiprocessing.Process.name")). *args* - кортеж аргументов для целевого вызова. *kwargs* - словарь ключевой аргументов для целевого вызова. Если указано, только ключевой аргумент *daemon* задает для флага процесса [`daemon`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.daemon "multiprocessing.Process.daemon") значение `True` или `False`. Если значение равно `None` (по умолчанию), этот флаг наследуется от процесса создания. По умолчанию аргументы не передаются *target*. Если подкласс отвергает конструктора, он должен удостовериться, что призывает конструктора базового класса (`Process.__init__()`) прежде, чем сделать что-либо еще к процессу. Изменено в версии 3.3: Добавлен аргумент *daemon*. `run`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.run "Ссылка на это определение") Метод, представляющий активность процесса. Этот метод можно переопределить в подкласс. Стандартный метод [`run()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.run "multiprocessing.Process.run") призывает подлежащий выкупу объект, переданный конструктору объекта как целевой аргумент, если таковые имеются, с последовательными и аргументами ключевой, взятыми от *args* и аргументов *kwargs*, соответственно. `start`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.start "Ссылка на это определение") Запустите действие процесса. Это должно вызываться не более одного раза для каждого объекта процесса. Она обеспечивает возможность вызова метода [`run()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.run "multiprocessing.Process.run") объекта в отдельном процессе. `join`(\[*timeout*\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.join "Ссылка на это определение") Если необязательным аргументом *timeout* является `None` (по умолчанию), метод блокируется до завершения процесса, метод [`join()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.join "multiprocessing.Process.join") которого вызывается. Если *timeout* - положительное число, оно блокируется максимум через *timeout* секунд. Обратите внимание, что метод возвращает `None`, если его процесс завершается или время ожидания метода истекло. Проверьте [`exitcode`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.exitcode "multiprocessing.Process.exitcode") процесса, чтобы определить его завершение. Процесс может быть объединен много раз. Процесс не может присоединиться к самому себе, поскольку это приведет к взаимоблокировке. Ошибка при попытке присоединения к процессу перед его запуском. `name`[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.name "Ссылка на это определение") Имя процесса. Имя - строка используемый в идентификационных целях только. У него нет семантики. Нескольким процессам может быть присвоено одно и то же имя. Начальное имя задается конструктором. Если для конструктора не указано явное имя, создается имя формы „Process-N:sub:1: N:sub:2:…: N:sub:k“, где каждый Nk является N-м потомком своего родителя. `is_alive`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.is_alive "Ссылка на это определение") Возвращает жив ли процесс. Примерно, объект процесса жив с момента возвращает метода [`start()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.start "multiprocessing.Process.start") до завершения дочернего процесса. `daemon`[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.daemon "Ссылка на это определение") Флаг демона процесса, логический значение. Это должно быть установлено, прежде чем [`start()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.start "multiprocessing.Process.start") называют. Начальный значение унаследован от процесса создания. Когда процесс завершается, он пытается завершить все свои демонические дочерние процессы. Обратите внимание, что демоническому процессу запрещено создавать дочерние процессы. В противном случае демонический процесс оставит своих потомков сиротами, если он завершится после завершения родительского процесса. Кроме того, это демоны или службы **не** Unix, это обычные процессы, которые будут прекращены (и не присоединены), если не демонические процессы вышли. В дополнение к [`threading.Thread`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.Thread "threading.Thread") API объекты [`Process`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process "multiprocessing.Process") также поддерживают следующий атрибуты и methods: `pid`[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.pid "Ссылка на это определение") Возвращает идентификатор процесса. Перед началом процесса это будет `None`. `exitcode`[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.exitcode "Ссылка на это определение") Выход ребенка код. Это будет `None`, если процесс еще не завершен. Отрицательный значение *\-N* указывает на то, что дочерний объект был завершен сигналом *N*. `authkey`[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.authkey "Ссылка на это определение") Ключ аутентификации процесса (байтовая строка). Когда [`multiprocessing`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing "multiprocessing: Процессный параллелизм.") инициализируется, основному процессу присваивается случайный строка с помощью [`os.urandom()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/os.html#os.urandom "os.urandom"). При создании объекта [`Process`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process "multiprocessing.Process") он наследует ключ аутентификации родительского процесса, хотя его можно изменить, установив для параметра [`authkey`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.authkey "multiprocessing.Process.authkey") значение другого байта строка. См. [Ключи аутентификации](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-auth-keys). `sentinel`[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.sentinel "Ссылка на это определение") Числовой дескриптор системного объекта, который становится «готовым» по завершении процесса. Вы можете использовать этот значение, если вы хотите ждать на нескольких событиях, сразу используя [`multiprocessing.connection.wait()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.wait "multiprocessing.connection.wait"). В противном случае вызов [`join()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.join "multiprocessing.Process.join") проще. В Windows это дескриптор ОС, используемый с семейством вызовов API `WaitForSingleObject` и `WaitForMultipleObjects`. На Unix это - файл дескриптор, применимый с примитивами от модуля [`select`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/select.html#module-select "select: Дождаться завершения I/O в нескольких потоках."). Добавлено в версии 3.3. `terminate`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.terminate "Ссылка на это определение") Завершить процесс. В Unix это выполняется с помощью сигнала `SIGTERM`; на Windows используется `TerminateProcess()`. Следует отметить, что обработчики exit и finally и т.д. выполняться не будут. Заметим, что потомки процесса *не* будут прекращены - они просто осиротеют. Предупреждение Если этот метод является используемый, когда связанный процесс использует пайп или очередь, то пайп или очередь может быть повреждена и может стать непригодной для использования другим процессом. Аналогично, если процесс приобрел блокировку или семафор и т.д., то завершение его может привести к взаимоблокировке других процессов. `kill`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.kill "Ссылка на это определение") То же, что и [`terminate()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.terminate "multiprocessing.Process.terminate"), но с использованием сигнала `SIGKILL` в Unix. Добавлено в версии 3.7. `close`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.close "Ссылка на это определение") Закрыть объект [`Process`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process "multiprocessing.Process"), освободив все связанные с ним ресурсы. [`ValueError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#ValueError "ValueError") возникает, если базовый процесс все еще выполняется. Как только [`close()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.close "multiprocessing.Process.close") возвращает успешно, большинство других методов и атрибуты объекта [`Process`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process "multiprocessing.Process") поднимут [`ValueError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#ValueError "ValueError"). Добавлено в версии 3.7. Обратите внимание, что [`start()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.start "multiprocessing.Process.start"), [`join()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.join "multiprocessing.Process.join"), [`is_alive()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.is_alive "multiprocessing.Process.is_alive"), [`terminate()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.terminate "multiprocessing.Process.terminate") и методы [`exitcode`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.exitcode "multiprocessing.Process.exitcode") должен только вызвать процесс, который создал объект процесса. Пример использования некоторых методов [`Process`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process "multiprocessing.Process"): ``` >>> import multiprocessing, time, signal >>> p = multiprocessing.Process(target=time.sleep, args=(1000,)) >>> print(p, p.is_alive()) <Process ... initial> False >>> p.start() >>> print(p, p.is_alive()) <Process ... started> True >>> p.terminate() >>> time.sleep(0.1) >>> print(p, p.is_alive()) <Process ... stopped exitcode=-SIGTERM> False >>> p.exitcode == -signal.SIGTERM True ``` *exception* `multiprocessing.``ProcessError`[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.ProcessError "Ссылка на это определение") Базовый класс всех исключений [`multiprocessing`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing "multiprocessing: Процессный параллелизм."). *exception* `multiprocessing.``BufferTooShort`[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.BufferTooShort "Ссылка на это определение") Исключение, вызванное `Connection.recv_bytes_into()`, когда предоставленный объект буфера слишком мал для чтения сообщения. Если `e` является сущность [`BufferTooShort`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.BufferTooShort "multiprocessing.BufferTooShort"), то `e.args[0]` передаст сообщение в виде байтовой строки. *exception* `multiprocessing.``AuthenticationError`[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.AuthenticationError "Ссылка на это определение") Возникает при ошибке проверки подлинности. *exception* `multiprocessing.``TimeoutError`[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.TimeoutError "Ссылка на это определение") Вызывается методами с тайм-аутом по истечении тайм-аута. ### Пайпы и очереди[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id9 "Ссылка на этот заголовок") При использовании нескольких процессов обычно используют передачу сообщений для связи между процессами и избегают необходимости использования каких-либо примитивов синхронизации, таких как блокировки. Для передачи сообщений можно использовать [`Pipe()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Pipe "multiprocessing.Pipe") (для соединения между двумя процессами) или очередь (которая позволяет нескольким производителям и потребителям). [`Queue`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue "multiprocessing.Queue"), [`SimpleQueue`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.SimpleQueue "multiprocessing.SimpleQueue") и типы [`JoinableQueue`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.JoinableQueue "multiprocessing.JoinableQueue") - мультипроизводитель, мультипотребитель очереди FIFO, смоделированные на классе [`queue.Queue`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/queue.html#queue.Queue "queue.Queue") в стандартной библиотеке. Они отличаются по тому [`Queue`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue "multiprocessing.Queue"), испытывает недостаток в [`task_done()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/queue.html#queue.Queue.task_done "queue.Queue.task_done") и методах [`join()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/queue.html#queue.Queue.join "queue.Queue.join"), введенных в класс Python 2.5’s [`queue.Queue`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/queue.html#queue.Queue "queue.Queue"). Если вы используете [`JoinableQueue`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.JoinableQueue "multiprocessing.JoinableQueue"), то вы **должны** вызвать [`JoinableQueue.task_done()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.JoinableQueue.task_done "multiprocessing.JoinableQueue.task_done") для каждой задачи, удаленной из очереди, или семафор используемый для подсчета количества незавершенных задач может в конечном итоге переполниться, вызывая исключение. Обратите внимание, что можно также создать общую очередь с помощью объекта менеджера - см. раздел [Менеджеры](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-managers). Примечание [`multiprocessing`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing "multiprocessing: Процессный параллелизм.") использует обычные исключения [`queue.Empty`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/queue.html#queue.Empty "queue.Empty") и [`queue.Full`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/queue.html#queue.Full "queue.Full") для сигнализации тайм-аута. Они недоступны в пространстве имен [`multiprocessing`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing "multiprocessing: Процессный параллелизм."), поэтому их необходимо импортировать из [`queue`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/queue.html#module-queue "queue: Класс синхронизированной очереди."). Примечание Когда объект помещен на очередь, объект - pickled и фон поток более поздние потоки данные pickled к основному пайп. Это имеет некоторые последствия, которые немного удивительны, но не должны вызывать никаких практических трудностей - если они действительно беспокоят вас, то вы можете вместо этого использовать очередь, созданную с [manager](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-managers). 1. После помещения объекта в пустую очередь может произойти бесконечная задержка перед тем, как метод [`empty()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue.empty "multiprocessing.Queue.empty") очереди возвращает [`False`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/constants.html#False "False") и [`get_nowait()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue.get_nowait "multiprocessing.Queue.get_nowait") может возвращает без повышения [`queue.Empty`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/queue.html#queue.Empty "queue.Empty"). 2. если несколько процессов ставят в очередь объекты, возможно, чтобы объекты были приняты на другом конце вне порядка. Однако объекты, поставленные в очередь одним и тем же процессом, всегда будут находиться в ожидаемом порядке относительно друг друга. Предупреждение Если процесс был убит с помощью [`Process.terminate()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.terminate "multiprocessing.Process.terminate") или [`os.kill()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/os.html#os.kill "os.kill") во время попытки использования [`Queue`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue "multiprocessing.Queue"), то данные в очереди, вероятно, будут повреждены. Это может привести к тому, что любой другой процесс получит исключение при попытке использовать очередь позже. Предупреждение Как упомянуто выше, если дочерний процесс поместил предметы на очередь (и у него нет используемый [`JoinableQueue.cancel_join_thread`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue.cancel_join_thread "multiprocessing.Queue.cancel_join_thread")), тогда тот процесс не закончится, пока все буферизированные предметы не смылись (flushed) в пайп. Это означает, что при попытке присоединения к этому процессу может возникнуть взаимоблокировка, если вы не уверены, что все элементы, помещенные в очередь, были израсходованы. Аналогично, если дочерний процесс не является демоническим, то родительский процесс может зависать на выходе, когда пытается присоединиться ко всем своим недемоническим потомкам. Обратите внимание, что очередь, созданная с помощью менеджера, не имеет этой проблемы. См. [Программирование рекомендаций](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-programming). Пример использования очередей для межпроцессной связи см. в разделе [Примеры](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-examples). `multiprocessing.``Pipe`(\[*duplex*\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Pipe "Ссылка на это определение") Возвращает пару `(conn1, conn2)` объектов [`Connection`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Connection "multiprocessing.connection.Connection"), представляющих концы пайпа. Если *duplex* равно `True` (по умолчанию), то пайп является двунаправленным. Если *duplex* - `False` тогда, пайп однонаправлен: `conn1` может только быть используемый для получения сообщений, и `conn2` может только быть используемый для отправки сообщений. *class* `multiprocessing.``Queue`(\[*maxsize*\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue "Ссылка на это определение") Возвращает общую очередь процесса, реализованную с использованием пайп и нескольких блокировок/семафоров. Когда процесс сначала помещает элемент в очередь, запускается питатель поток, который передает объекты из буфера в пайп. Обычные исключения [`queue.Empty`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/queue.html#queue.Empty "queue.Empty") и [`queue.Full`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/queue.html#queue.Full "queue.Full") из модуля [`queue`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/queue.html#module-queue "queue: Класс синхронизированной очереди.") стандартной библиотеки вызываются тайм-аутами сигнала. [`Queue`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue "multiprocessing.Queue") реализует все методы [`queue.Queue`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/queue.html#queue.Queue "queue.Queue"), кроме [`task_done()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/queue.html#queue.Queue.task_done "queue.Queue.task_done") и [`join()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/queue.html#queue.Queue.join "queue.Queue.join"). `qsize`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue.qsize "Ссылка на это определение") Возвращает приблизительный размер очереди. Из-за семантики многопоточной/многопроцессорной обработки это число не является надежным. Обратите внимание, что это может привести к появлению [`NotImplementedError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#NotImplementedError "NotImplementedError") на платформах Unix, таких как Mac OS X, где `sem_getvalue()` не реализован. `empty`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue.empty "Ссылка на это определение") Возвращает `True`, если очередь пуста, `False` иначе. Из-за семантики многопоточной/многопроцессорной обработки это ненадежно. `full`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue.full "Ссылка на это определение") Возвращает `True`, если очередь полна, `False` иначе. Из-за семантики многопоточной/многопроцессорной обработки это ненадежно. `put`(*obj*\[, *block*\[, *timeout*\]\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue.put "Ссылка на это определение") Поместить объект в очередь. Если дополнительный аргумент *block* имеет значение `True` (по умолчанию), а *timeout* - значение `None` (по умолчанию), при необходимости блокируйте до тех пор, пока свободный слот не будет доступен. Если *timeout* является положительным числом, он блокирует максимум *timeout* секунд и вызывает исключение [`queue.Full`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/queue.html#queue.Full "queue.Full"), если свободный слот не был доступен в течение этого времени. В противном случае (*block* - `False`) Поместить элемент в очередь, если свободный слот немедленно доступен, иначе вызовите исключение [`queue.Full`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/queue.html#queue.Full "queue.Full") (*timeout* игнорируется в этом случае). Изменено в версии 3.8: Если очередь закрыта, [`ValueError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#ValueError "ValueError") поднят вместо [`AssertionError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#AssertionError "AssertionError"). `put_nowait`(*obj*)[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue.put_nowait "Ссылка на это определение") Эквивалентный `put(obj, False)`. `get`(\[*block*\[, *timeout*\]\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue.get "Ссылка на это определение") Удаление и возвращает элемента из очереди. Если необязательными args *block* является `True` (по умолчанию), а *timeout* - `None` (по умолчанию), при необходимости блокируйте до тех пор, пока элемент не будет доступен. Если *timeout* является положительным числом, он блокирует максимум *timeout* секунд и вызывает исключение [`queue.Empty`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/queue.html#queue.Empty "queue.Empty"), если за это время не было доступно ни одного элемента. В противном случае (блок - `False`), возвращает элемент, если он немедленно доступен, иначе вызовите исключение [`queue.Empty`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/queue.html#queue.Empty "queue.Empty") (в этом случае *timeout* игнорируется). Изменено в версии 3.8: Если очередь закрыта, [`ValueError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#ValueError "ValueError") поднят вместо [`OSError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#OSError "OSError"). `get_nowait`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue.get_nowait "Ссылка на это определение") Эквивалентный `get(False)`. [`multiprocessing.Queue`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue "multiprocessing.Queue") имеет несколько дополнительных методов, не найденных в [`queue.Queue`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/queue.html#queue.Queue "queue.Queue"). Эти методы обычно не нужны для большинства код: `close`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue.close "Ссылка на это определение") Укажите, что текущий процесс больше не будет помещать данные в эту очередь. Фоновый поток завершит работу после очистки всех буферизованных данных в пайп. Это вызывается автоматически при сборе мусора в очередь. `join_thread`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue.join_thread "Ссылка на это определение") Присоединиться к фоновому потоку. Это может только быть используемый после того, как вызван [`close()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue.close "multiprocessing.Queue.close"). Это блокирует до фона выходы поток, гарантируя, что все данные в буфере смылись (flushed) в пайп. По умолчанию, если процесс не является создателем очереди, при выходе он попытается присоединиться к фоновому поток очереди. Процесс может вызвать [`cancel_join_thread()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue.cancel_join_thread "multiprocessing.Queue.cancel_join_thread"), чтобы заставить [`join_thread()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue.join_thread "multiprocessing.Queue.join_thread") ничего не делать. `cancel_join_thread`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue.cancel_join_thread "Ссылка на это определение") Препятствуйте тому, чтобы [`join_thread()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue.join_thread "multiprocessing.Queue.join_thread") блокировал. В частности, это предотвращает автоматическое соединение фоновых поток при завершении процесса – см. раздел [`join_thread()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue.join_thread "multiprocessing.Queue.join_thread"). Лучшее имя для этого метода может быть `allow_exit_without_flush()`. Вероятно, это приведет к потере поставленных в очередь данных, и вам почти наверняка не потребуется их использовать. Это действительно только в том случае, если необходимо, чтобы текущий процесс немедленно вышел, не дожидаясь очистки поставленных в очередь данных на основной пайп, и вы не заботитесь о потерянных данных. Примечание Функциональность этого класса требует функциональной реализации общего семафора в операционной системе хоста. Без него функциональность этого класса будет отключена, и попытки создания экземпляра [`Queue`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue "multiprocessing.Queue") приведут к появлению [`ImportError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#ImportError "ImportError"). Дополнительные сведения см. в разделе [bpo-3770](https://bugs.python.org/issue3770). То же самое относится и к любому из перечисленных ниже типов специализированных очередей. *class* `multiprocessing.``SimpleQueue`[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.SimpleQueue "Ссылка на это определение") Это упрощенный тип [`Queue`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue "multiprocessing.Queue"), очень близкий к заблокированному [`Pipe`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Pipe "multiprocessing.Pipe"). `empty`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.SimpleQueue.empty "Ссылка на это определение") Возвращает `True`, если очередь пуста, `False` иначе. `get`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.SimpleQueue.get "Ссылка на это определение") Удаление и возвращает элемента из очереди. `put`(*item*)[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.SimpleQueue.put "Ссылка на это определение") Поместить *item* в очередь. *class* `multiprocessing.``JoinableQueue`(\[*maxsize*\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.JoinableQueue "Ссылка на это определение") [`JoinableQueue`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.JoinableQueue "multiprocessing.JoinableQueue"), [`Queue`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue "multiprocessing.Queue") подкласс, представляет собой очередь, которая дополнительно содержит методы [`task_done()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.JoinableQueue.task_done "multiprocessing.JoinableQueue.task_done") и [`join()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.JoinableQueue.join "multiprocessing.JoinableQueue.join"). `task_done`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.JoinableQueue.task_done "Ссылка на это определение") Укажите, что ранее поставленная в очередь задача завершена. Используется потребителями очереди. Для каждого [`get()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue.get "multiprocessing.Queue.get") используемый, чтобы выбрать задачу, последующий вызов [`task_done()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.JoinableQueue.task_done "multiprocessing.JoinableQueue.task_done") сообщает очереди, что обработка задачи завершена. Если [`join()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/queue.html#queue.Queue.join "queue.Queue.join") в настоящее время заблокирует, то он возобновит, когда все предметы были обработаны (подразумевать, что требование [`task_done()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.JoinableQueue.task_done "multiprocessing.JoinableQueue.task_done") было получено для каждого предмета, который был [`put()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue.put "multiprocessing.Queue.put") в очередь). Вызывает [`ValueError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#ValueError "ValueError"), если вызывается больше раз, чем было элементов, помещенных в очередь. `join`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.JoinableQueue.join "Ссылка на это определение") Блокировать до тех пор, пока все элементы в очереди не будут получены и обработаны. Количество незавершенных задач увеличивается при каждом добавлении элемента в очередь. Счетчик снижается всякий раз, когда потребитель звонит [`task_done()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.JoinableQueue.task_done "multiprocessing.JoinableQueue.task_done"), чтобы указать, что элемент был извлечен, и вся работа над ним завершена. Когда число незавершенных задач падает до нуля, [`join()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/queue.html#queue.Queue.join "queue.Queue.join") разблокирует. ### Разное[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id10 "Ссылка на этот заголовок") `multiprocessing.``active_children`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.active_children "Ссылка на это определение") Возвращает список всех живых потомков текущего процесса. Вызов этого метода имеет побочный эффект «присоединения» к любым уже завершенным процессам. `multiprocessing.``cpu_count`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.cpu_count "Ссылка на это определение") Возвращает количество ЦПУ в системе. Это число не эквивалентно числу ЦПУ, которые может использовать текущий процесс. Количество используемых ЦПУ можно получить с помощью `len(os.sched_getaffinity(0))` Может поднять [`NotImplementedError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#NotImplementedError "NotImplementedError"). См.также [`os.cpu_count()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/os.html#os.cpu_count "os.cpu_count") `multiprocessing.``current_process`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.current_process "Ссылка на это определение") Возвращает объект [`Process`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process "multiprocessing.Process"), соответствующий текущему процессу. Аналог [`threading.current_thread()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.current_thread "threading.current_thread"). `multiprocessing.``parent_process`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.parent_process "Ссылка на это определение") Возвращает объект [`Process`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process "multiprocessing.Process"), соответствующий родительскому процессу [`current_process()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.current_process "multiprocessing.current_process"). Для основного процесса `parent_process` будет `None`. Добавлено в версии 3.8. `multiprocessing.``freeze_support`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.freeze_support "Ссылка на это определение") Добавление поддержки в том случае, если программа, использующая [`multiprocessing`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing "multiprocessing: Процессный параллелизм."), была заморожена для создания исполняемого файла Windows. (Был проверен с помощью **py2exe**, **PyInstaller** и **cx\_Freeze**.) Эту функцию необходимо вызвать непосредственно после `if __name__ == '__main__'` линии основного модуля. Например: ``` from multiprocessing import Process, freeze_support def f(): print('hello world!') if __name__ == '__main__': freeze_support() Process(target=f).start() ``` Если строка `freeze_support()` опущена, то попытка запуска замороженного исполняемого файла вызовет [`RuntimeError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#RuntimeError "RuntimeError"). `freeze_support()` запроса не имеет никакого эффекта, когда он призван на любую операционную систему кроме Windows. Кроме того, если модулем управляет обычно Python интерпретатор на Windows (программа не была заморожена), то `freeze_support()` не имеет никакого эффекта. `multiprocessing.``get_all_start_methods`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.get_all_start_methods "Ссылка на это определение") Возвращает список поддерживаемых методов запуска, первым из которых является метод по умолчанию. Возможные методы запуска: `'fork'`, `'spawn'` и `'forkserver'`. В Windows доступен только `'spawn'`. На Unix `'fork'` и `'spawn'` всегда поддерживаются, при этом `'fork'` - дефолт. Добавлено в версии 3.4. `multiprocessing.``get_context`(*method=None*)[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.get_context "Ссылка на это определение") Возвращает объект контекст, имеющий ту же атрибуты, что и модуль [`multiprocessing`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing "multiprocessing: Процессный параллелизм."). Если *method* - `None` тогда дефолт, контекст - возвращенный. В противном случае *method* должны быть `'fork'`, `'spawn'`, `'forkserver'`. [`ValueError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#ValueError "ValueError") возникает, если указанный метод запуска недоступен. Добавлено в версии 3.4. `multiprocessing.``get_start_method`(*allow\_none=False*)[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.get_start_method "Ссылка на это определение") Возвращает имя метода запуска используемый для запуска процессов. Если метод начала не был исправлен, и *allow\_none* ложный, то метод начала прикреплен к дефолту, и имя - возвращенный. Если метод запуска не был фиксирован, а *allow\_none* имеет значение true, то `None` имеет значение возвращенный. возвращает значение может быть `'fork'`, `'spawn'`, `'forkserver'` или `None`. `'fork'` является значением по умолчанию в Unix, а `'spawn'` - значением по умолчанию в Windows. Добавлено в версии 3.4. `multiprocessing.``set_executable`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.set_executable "Ссылка на это определение") Задает путь к Python интерпретатор, который будет использоваться при запуске дочернего процесса. (По умолчанию [`sys.executable`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/sys.html#sys.executable "sys.executable") - используемый). Встраивающие устройства, вероятно, должны будут сделать что-то вроде: ``` set_executable(os.path.join(sys.exec_prefix, 'pythonw.exe')) ``` прежде чем они смогут создавать дочерние процессы. Изменено в версии 3.4: Теперь поддержанный на Unix, когда метод начала `'spawn'` - используемый. `multiprocessing.``set_start_method`(*method*)[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.set_start_method "Ссылка на это определение") Установите метод, который должен быть используемый, чтобы начать дочерние процессы. *method* может быть `'fork'`, `'spawn'` или `'forkserver'`. Следует отметить, что это должно вызываться не более одного раза и должно быть защищено внутри `if __name__ == '__main__'` клаузула основного модуля. Добавлено в версии 3.4. Примечание [`multiprocessing`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing "multiprocessing: Процессный параллелизм.") не содержит аналогов [`threading.active_count()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.active_count "threading.active_count"), [`threading.enumerate()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.enumerate "threading.enumerate"), [`threading.settrace()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.settrace "threading.settrace"), [`threading.setprofile()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.setprofile "threading.setprofile"), [`threading.Timer`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.Timer "threading.Timer") или [`threading.local`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.local "threading.local"). ### Объекты связи[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id11 "Ссылка на этот заголовок") Объекты соединения позволяют отправлять и принимать выбираемые объекты или строки. Они могут рассматриваться как связанные сокеты, ориентированные на сообщение. Объекты соединения обычно создаются с помощью [`Pipe`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Pipe "multiprocessing.Pipe") – см. также раздел [Слушатели и клиенты](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-listeners-clients). *class* `multiprocessing.connection.``Connection`[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Connection "Ссылка на это определение") `send`(*obj*)[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Connection.send "Ссылка на это определение") Отправьте объект на другой конец соединения, который следует прочитать с помощью команды [`recv()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Connection.recv "multiprocessing.connection.Connection.recv"). Объект должен быть подбираемым. Очень большие огурцы (приблизительно 32 MiB +, хотя это зависит от ОС) могут вызвать исключение [`ValueError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#ValueError "ValueError"). `recv`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Connection.recv "Ссылка на это определение") Возвращает объект, отправленный с другого конца соединения с помощью команды [`send()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Connection.send "multiprocessing.connection.Connection.send"). Блокируется, пока не будет что получить. Поднимает [`EOFError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#EOFError "EOFError"), если ничего не осталось получить, а другой конец был закрыт. `fileno`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Connection.fileno "Ссылка на это определение") Возвращает файл дескриптор или дескриптор используемый по соединению. `close`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Connection.close "Ссылка на это определение") Закрыть связь. Это вызывается автоматически при сборе мусора соединения. `poll`(\[*timeout*\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Connection.poll "Ссылка на это определение") Возвращает, имеются ли данные, доступные для чтения. Если *timeout* не указан, то он будет возвращает немедленно. Если *timeout* - число, это указывает максимальное время блокировки в секундах. Если *timeout* `None`, то бесконечное время ожидания равно используемый. Следует отметить, что несколько объектов соединения могут опрашиваться одновременно с помощью функции [`multiprocessing.connection.wait()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.wait "multiprocessing.connection.wait"). `send_bytes`(*buffer*\[, *offset*\[, *size*\]\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Connection.send_bytes "Ссылка на это определение") Отправка байтовых данных из [байтоподобного объекта](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/glossary.html#term-15) в виде полного сообщения. Если задано значение *offset*, то данные считываются из этой позиции в *buffer*. Если задано значение *size*, то многие байты будут считываться из буфера. Очень большие буферы (приблизительно 32 MiB +, хотя это зависит от ОС) могут вызвать исключение [`ValueError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#ValueError "ValueError") `recv_bytes`(\[*maxlength*\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Connection.recv_bytes "Ссылка на это определение") Возвращает полное сообщение байтовых данных, отправленное с другого конца соединения в виде строка. Блокируется, пока не будет что получить. Поднимает [`EOFError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#EOFError "EOFError"), если ничего не осталось получить, а другой конец закрылся. Если задано значение *maxlength*, и сообщение длиннее *maxlength*, то [`OSError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#OSError "OSError") возникает, и соединение будет недоступно для чтения. Изменено в версии 3.3: Используемая функция поднимает [`IOError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#IOError "IOError"), которое теперь является алиасом [`OSError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#OSError "OSError"). `recv_bytes_into`(*buffer*\[, *offset*\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Connection.recv_bytes_into "Ссылка на это определение") Считывание в *buffer* полного сообщения байтовых данных, отправленных с другого конца соединения, и возвращает количества байтов в сообщении. Блокируется, пока не будет что получить. Поднимает [`EOFError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#EOFError "EOFError"), если ничего не осталось получить, а другой конец был закрыт. *buffer* должен быть записываемым [байтоподобным объектом](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/glossary.html#term-15). Если задано значение *offset*, то сообщение будет записано в буфер из этой позиции. Смещение должно быть неотрицательным целым числом, меньшим длины *buffer* (в байтах). Если буфер слишком короткий, то возникает исключение `BufferTooShort` и полное сообщение доступно как `e.args[0]` где `e` - исключение сущность. Изменено в версии 3.3: Сами объекты соединения теперь могут переноситься между процессами с помощью [`Connection.send()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Connection.send "multiprocessing.connection.Connection.send") и [`Connection.recv()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Connection.recv "multiprocessing.connection.Connection.recv"). Добавлено в версии 3.3: Объекты соединения теперь поддерживают протокол управления контекст - см. раздел [Типы менеджера контекста](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/stdtypes.html#typecontextmanager). [`__enter__()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/stdtypes.html#contextmanager.__enter__ "contextmanager.__enter__") возвращает объект подключения, а [`__exit__()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/stdtypes.html#contextmanager.__exit__ "contextmanager.__exit__") вызывает [`close()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Connection.close "multiprocessing.connection.Connection.close"). Например: \>\>\> ``` >>> from multiprocessing import Pipe >>> a, b = Pipe() >>> a.send([1, 'hello', None]) >>> b.recv() [1, 'hello', None] >>> b.send_bytes(b'thank you') >>> a.recv_bytes() b'thank you' >>> import array >>> arr1 = array.array('i', range(5)) >>> arr2 = array.array('i', [0] * 10) >>> a.send_bytes(arr1) >>> count = b.recv_bytes_into(arr2) >>> assert count == len(arr1) * arr1.itemsize >>> arr2 array('i', [0, 1, 2, 3, 4, 0, 0, 0, 0, 0]) ``` Предупреждение Метод [`Connection.recv()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Connection.recv "multiprocessing.connection.Connection.recv") автоматически отключает полученные данные, что может быть угрозой безопасности, если вы не можете доверять процессу, отправившему сообщение. Поэтому, если объект подключения не был создан с помощью `Pipe()`, следует использовать методы [`recv()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Connection.recv "multiprocessing.connection.Connection.recv") и [`send()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Connection.send "multiprocessing.connection.Connection.send") только после выполнения той или иной аутентификации. См. [Ключи аутентификации](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-auth-keys). Предупреждение Если процесс погибает, когда он пытается прочитать или записать в пайп, то данные в пайп, вероятно, будут повреждены, поскольку может оказаться невозможным убедиться, где лежат границы сообщения. ### Примитивы синхронизации[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id12 "Ссылка на этот заголовок") Обычно примитивы синхронизации не так необходимы в многопроцессорной программе, как в многопоточной программе. См. документацию по модулю [`threading`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#module-threading "threading: Потоковый параллелизм."). Обратите внимание, что можно также создать примитивы синхронизации с помощью объекта менеджера - см. раздел [Менеджеры](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-managers). *class* `multiprocessing.``Barrier`(*parties*\[, *action*\[, *timeout*\]\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Barrier "Ссылка на это определение") Объект барьер: клон [`threading.Barrier`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.Barrier "threading.Barrier"). Добавлено в версии 3.3. *class* `multiprocessing.``BoundedSemaphore`(\[*value*\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.BoundedSemaphore "Ссылка на это определение") Барьерный семафорный объект: близкий аналог [`threading.BoundedSemaphore`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.BoundedSemaphore "threading.BoundedSemaphore"). Существует одиночное отличие от его близкого аналога: первый аргумент его метода `acquire` называется *block*, как это согласуется с [`Lock.acquire()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Lock.acquire "multiprocessing.Lock.acquire"). Примечание В Mac OS X это неотличимо от [`Semaphore`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Semaphore "multiprocessing.Semaphore"), потому что `sem_getvalue()` не реализована на этой платформе. *class* `multiprocessing.``Condition`(\[*lock*\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Condition "Ссылка на это определение") Переменная условия: алиас для [`threading.Condition`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.Condition "threading.Condition"). Если задано значение *lock*, то это должен быть объект [`Lock`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Lock "multiprocessing.Lock") или [`RLock`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.RLock "multiprocessing.RLock") из [`multiprocessing`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing "multiprocessing: Процессный параллелизм."). Изменено в версии 3.3: Добавлен метод [`wait_for()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.Condition.wait_for "threading.Condition.wait_for"). *class* `multiprocessing.``Event`[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Event "Ссылка на это определение") Клон [`threading.Event`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.Event "threading.Event"). *class* `multiprocessing.``Lock`[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Lock "Ссылка на это определение") Нерекурсивный объект блокировки: близкий аналог [`threading.Lock`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.Lock "threading.Lock"). Как только процесс или поток приобрел блокировку, последующие попытки получить ее от любого процесса или поток будут блокироваться до тех пор, пока она не будет освобождена; любой процесс или поток может освободить его. Понятия и поведение [`threading.Lock`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.Lock "threading.Lock") в том виде, в каком они применяются к потоки, воспроизводятся здесь в [`multiprocessing.Lock`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Lock "multiprocessing.Lock"), как это применимо к процессам или потоки, за исключением отмеченных. Обратите внимание, что [`Lock`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Lock "multiprocessing.Lock") - на самом деле фабричная функция, какой возвращает сущность `multiprocessing.synchronize.Lock` инициализировал с дефолтом контекст. [`Lock`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Lock "multiprocessing.Lock") поддерживает протокол [контекстного менеджера](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/glossary.html#term-22) и таким образом может быть используемый в [`with`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/reference/compound_stmts.html#with) инструкции. `acquire`(*block=True*, *timeout=None*)[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Lock.acquire "Ссылка на это определение") Получить блокировку, блокировку или неблокировку. Если для аргумента *block* установлено значение `True` (значение по умолчанию), вызов метода будет блокироваться до тех пор, пока блокировка не окажется в разблокированном состояние, а затем будет установлен параметр locked и возвращает `True`. Обратите внимание, что имя этого первого аргумента отличается от имени в [`threading.Lock.acquire()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.Lock.acquire "threading.Lock.acquire"). Если для аргумента *block* установлено значение `False`, вызов метода не блокируется. Если блокировка в данный момент находится в заблокированном состояние, возвращает `False`; в противном случае установите блокировку на заблокированный состояние и возвращает `True`. При вызове с положительным значение с плавающей запятой для *timeout* блок максимум на количество секунд, указанное параметром *timeout*, если блокировка не может быть получена. Просьбы с отрицательным значение для *timeout* эквивалентны *timeout* ноля. Вызовы с *timeout* значение `None` (по умолчанию) устанавливают период тайм-аута как бесконечный. Отметим, что лечение отрицательного или `None` значения для *timeout* отличается от реализованного поведения в [`threading.Lock.acquire()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.Lock.acquire "threading.Lock.acquire"). Аргумент *timeout* не имеет практических последствий, если аргумент *block* имеет значение `False` и, таким образом, игнорируется. Возвращает `True` если блокировка была приобретена или `False`, если истек период ожидания. `release`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Lock.release "Ссылка на это определение") Отпустите замок. Это может быть вызвано из любого процесса или поток, а не только из процесса или поток, которые первоначально приобрели блокировку. Поведение аналогично поведению в [`threading.Lock.release()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.Lock.release "threading.Lock.release"), за исключением того, что при вызове на разблокированной блокировке возникает [`ValueError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#ValueError "ValueError"). *class* `multiprocessing.``RLock`[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.RLock "Ссылка на это определение") Объект рекурсивной блокировки: близкий аналог [`threading.RLock`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.RLock "threading.RLock"). Рекурсивная блокировка должна быть разблокирована процессом или поток, получившим ее. Как только процесс или поток приобрел рекурсивную блокировку, тот же самый процесс или поток может снова получить ее без блокировки; этот процесс или поток должны выпускать его один раз в каждый раз, когда он был приобретен. Обратите внимание, что [`RLock`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.RLock "multiprocessing.RLock") - на самом деле фабричная функция, какой возвращает сущность `multiprocessing.synchronize.RLock` инициализировал с дефолтом контекст. [`RLock`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.RLock "multiprocessing.RLock") поддерживает протокол [контекстного менеджера](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/glossary.html#term-22) и таким образом может быть используемый в [`with`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/reference/compound_stmts.html#with) инструкции. `acquire`(*block=True*, *timeout=None*)[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.RLock.acquire "Ссылка на это определение") Получить блокировку, блокировку или неблокировку. При вызове с аргументом *block*, имеющим значение `True`, блокировать до тех пор, пока блокировка не окажется в разблокированном состояние (не принадлежащем какому-либо процессу или поток), пока блокировка уже не принадлежит текущему процессу или поток. Текущий процесс или поток затем получает право собственности на блокировку (если она еще не имеет права собственности), а уровень рекурсии внутри блокировки увеличивается на единицу, что приводит к возвращает значение `True`. Обратите внимание, что в поведении этого первого аргумента существует несколько различий по сравнению с реализацией [`threading.RLock.acquire()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.RLock.acquire "threading.RLock.acquire"), начиная с имени самого аргумента. При вызове с аргументом *block*, имеющим значение `False`, не блокируйте. Если замок был уже приобретен (и таким образом принадлежит) другим процессом или поток, текущий процесс или поток не берут собственность, и уровень рекурсии в замке не изменен, приведя к возвращает значение `False`. Если блокировка находится в разблокированном состояние, текущий процесс или поток становится владельцем и уровень рекурсии увеличивается, что приводит к возвращает значение `True`. Использование и поведение аргумента *timeout* такие же, как и в [`Lock.acquire()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Lock.acquire "multiprocessing.Lock.acquire"). Обратите внимание, что некоторые из этих поведений *timeout* отличаются от реализованных поведений в [`threading.RLock.acquire()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.RLock.acquire "threading.RLock.acquire"). `release`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.RLock.release "Ссылка на это определение") Разблокируйте блокировку, уменьшая уровень рекурсии. Если после уменьшения уровень рекурсии равен нулю, сбросьте блокировку на разблокированную (не принадлежащую какому-либо процессу или поток) и если какие-либо другие процессы или потоки заблокированы в ожидании разблокировки блокировки, разрешите выполнение только одного из них. Если после уменьшения уровень рекурсии остается ненулевым, блокировка остается заблокированной и принадлежит вызывающему процессу или поток. Только назовите этот метод, когда процесс запроса или поток будут владеть замком. [`AssertionError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#AssertionError "AssertionError") поднят, если этот метод называют процесс или поток кроме владельца или если замок находится в незапертом (ненаходящемся в собственности) состояние. Обратите внимание, что тип исключения, вызванного в этой ситуации, отличается от реализованного поведения в [`threading.RLock.release()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.RLock.release "threading.RLock.release"). *class* `multiprocessing.``Semaphore`(\[*value*\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Semaphore "Ссылка на это определение") Семафорный объект: близкий аналог [`threading.Semaphore`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.Semaphore "threading.Semaphore"). Существует одиночное отличие от его близкого аналога: первый аргумент его метода `acquire` называется *block*, как это согласуется с [`Lock.acquire()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Lock.acquire "multiprocessing.Lock.acquire"). Примечание В Mac OS X `sem_timedwait` не поддерживается, поэтому вызов `acquire()` с тайм-аутом будет эмулировать поведение этой функции с помощью спящего цикла. Примечание Если сигнал SIGINT, сгенерированный `Ctrl-C`, прибудет, в то время как главный поток заблокирован требованием к `BoundedSemaphore.acquire()`, [`Lock.acquire()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Lock.acquire "multiprocessing.Lock.acquire"), [`RLock.acquire()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.RLock.acquire "multiprocessing.RLock.acquire"), `Semaphore.acquire()`, `Condition.acquire()` или `Condition.wait()` тогда, требование будет немедленно прервано, и [`KeyboardInterrupt`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#KeyboardInterrupt "KeyboardInterrupt") будет поднят. Это отличается от поведения [`threading`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#module-threading "threading: Потоковый параллелизм."), где SIGINT будет игнорироваться во время выполнения эквивалентных блокирующих вызовов. Примечание Некоторые функциональные возможности этого пакета требуют функциональной реализации общего семафора в операционной системе хоста. Без него модуль `multiprocessing.synchronize` будет отключен, и попытки его импорта приведут к появлению [`ImportError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#ImportError "ImportError"). Дополнительные сведения см. в разделе [bpo-3770](https://bugs.python.org/issue3770). ### Разделенные объекты [`ctypes`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/ctypes.html#module-ctypes "ctypes: Python библиотека внешних функций.")[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#ctypes "Ссылка на этот заголовок") С помощью общей памяти можно создавать общие объекты, которые могут наследоваться дочерними процессами. `multiprocessing.``Value`(*typecode\_or\_type*, *\*args*, *lock=True*)[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Value "Ссылка на это определение") Возвращает объект [`ctypes`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/ctypes.html#module-ctypes "ctypes: Python библиотека внешних функций."), выделенный из общей памяти. По умолчанию возвращает значение фактически является синхронизированной оболочкой для объекта. К самому объекту можно получить доступ через *value* атрибут [`Value`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Value "multiprocessing.Value"). *typecode\_or\_type* определяет тип объекта возвращенный: это - или тип ctypes или один символ typecode доброго используемый модулем [`array`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/array.html#module-array "array: Пространственно-эффективные массивы типизированных числовых значений."). *\*args* передан конструктору для типа. Если *lock* равно `True` (по умолчанию), создается новый объект рекурсивной блокировки для синхронизации доступа к значение. Если *lock* является объектом [`Lock`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Lock "multiprocessing.Lock") или [`RLock`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.RLock "multiprocessing.RLock"), то это будет используемый для синхронизации доступа к значение. Если *lock* будет `False` тогда, то доступ к объекту возвращенный не будет автоматически защищен замком, таким образом, это не обязательно будет «безопасно от процесса». Операции как `+=`, которые включают прочитанный и пишут, не атомные. Так что, если для сущность, вы хотите атомарно увеличить общий значение это недостаточно, чтобы просто сделать: ``` counter.value += 1 ``` Предполагая, что связанная блокировка является рекурсивной (что по умолчанию), можно сделать: ``` with counter.get_lock(): counter.value += 1 ``` Обратите внимание, что *lock* является только ключевым аргументом. `multiprocessing.``Array`(*typecode\_or\_type*, *size\_or\_initializer*, *\**, *lock=True*)[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Array "Ссылка на это определение") Возвращает массив ctypes, выделенный из общей памяти. По умолчанию возвращает значение фактически является синхронизированной обёрткой для массива. *typecode\_or\_type* определяет тип элементов множества возвращенный: это - или тип ctypes или один символ typecode доброго используемый модулем [`array`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/array.html#module-array "array: Пространственно-эффективные массивы типизированных числовых значений."). Если *size\_or\_initializer* является целым числом, то он определяет длину массива, и массив будет первоначально обнулен. Иначе *size\_or\_initializer* - последовательность, которая является используемый, чтобы инициализировать множество и чья длина определяет длину множества. Если *lock* равно `True` (по умолчанию), создается новый объект блокировки для синхронизации доступа к значение. Если *lock* является объектом [`Lock`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Lock "multiprocessing.Lock") или [`RLock`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.RLock "multiprocessing.RLock"), то это будет используемый для синхронизации доступа к значение. Если *lock* будет `False` тогда, то доступ к объекту возвращенный не будет автоматически защищен замком, таким образом, это не обязательно будет «безопасно от процесса». Обратите внимание, что *lock* - ключевой только аргумент. Обратите внимание, что у множества [`ctypes.c_char`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/ctypes.html#ctypes.c_char "ctypes.c_char") есть *value* и *raw* атрибуты, которые позволяют использовать его, чтобы сохранить и восстановить строки. #### Модуль [`multiprocessing.sharedctypes`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing.sharedctypes "multiprocessing.sharedctypes: Аллоцировать объекты ctypes из общей памяти.")[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing.sharedctypes "Ссылка на этот заголовок") Модуль [`multiprocessing.sharedctypes`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing.sharedctypes "multiprocessing.sharedctypes: Аллоцировать объекты ctypes из общей памяти.") предоставляет функции для выделения объектов [`ctypes`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/ctypes.html#module-ctypes "ctypes: Python библиотека внешних функций.") из общей памяти, которые могут быть унаследованы дочерними процессами. Примечание Хотя можно сохранить указатель в общей памяти, помните, что это относится к расположению в адресном пространстве конкретного процесса. Однако указатель, вероятно, недействителен в контекст второго процесса, и попытка отсоединить указатель от второго процесса может вызвать сбой. `multiprocessing.sharedctypes.``RawArray`(*typecode\_or\_type*, *size\_or\_initializer*)[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.sharedctypes.RawArray "Ссылка на это определение") Возвращает массив ctypes, выделенный из общей памяти. *typecode\_or\_type* определяет тип элементов множества возвращенный: это - или тип ctypes или один символ typecode доброго используемый модулем [`array`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/array.html#module-array "array: Пространственно-эффективные массивы типизированных числовых значений."). Если *size\_or\_initializer* является целым числом, то он определяет длину массива, и массив будет первоначально обнулен. Иначе *size\_or\_initializer* - последовательность, которая является используемый, чтобы инициализировать множество и чья длина определяет длину множества. Обратите внимание, что настройка и получение элемента потенциально неатомны - вместо этого используйте команду [`Array()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.sharedctypes.Array "multiprocessing.sharedctypes.Array"), чтобы убедиться, что доступ автоматически синхронизирован с помощью блокировки. `multiprocessing.sharedctypes.``RawValue`(*typecode\_or\_type*, *\*args*)[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.sharedctypes.RawValue "Ссылка на это определение") Возвращает объект ctypes, выделенный из общей памяти. *typecode\_or\_type* определяет тип объекта возвращенный: это - или тип ctypes или один символ typecode доброго используемый модулем [`array`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/array.html#module-array "array: Пространственно-эффективные массивы типизированных числовых значений."). *\*args* передан конструктору для типа. Обратите внимание, что настройка и получение значение потенциально неатомны - вместо этого используйте [`Value()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.sharedctypes.Value "multiprocessing.sharedctypes.Value"), чтобы убедиться, что доступ автоматически синхронизирован с помощью блокировки. Обратите внимание, что массив [`ctypes.c_char`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/ctypes.html#ctypes.c_char "ctypes.c_char") имеет `value` и `raw` атрибуты, которые позволяют использовать его для хранения и извлечения строки - см. документацию для [`ctypes`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/ctypes.html#module-ctypes "ctypes: Python библиотека внешних функций."). `multiprocessing.sharedctypes.``Array`(*typecode\_or\_type*, *size\_or\_initializer*, *\**, *lock=True*)[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.sharedctypes.Array "Ссылка на это определение") То же как [`RawArray()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.sharedctypes.RawArray "multiprocessing.sharedctypes.RawArray") за исключением того, что в зависимости от значение *lock* безопасная от процесса обертка синхронизации может быть возвращенный вместо сырья ctypes множество. Если *lock* равно `True` (по умолчанию), создается новый объект блокировки для синхронизации доступа к значение. Если *lock* является объектом [`Lock`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Lock "multiprocessing.Lock") или [`RLock`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.RLock "multiprocessing.RLock"), то это будет используемый для синхронизации доступа к значение. Если *lock* будет `False` тогда, то доступ к объекту возвращенный не будет автоматически защищен замком, таким образом, это не обязательно будет «безопасно от процесса». Обратите внимание, что *lock* является толко ключевым аргументом. `multiprocessing.sharedctypes.``Value`(*typecode\_or\_type*, *\*args*, *lock=True*)[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.sharedctypes.Value "Ссылка на это определение") То же как [`RawValue()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.sharedctypes.RawValue "multiprocessing.sharedctypes.RawValue") за исключением того, что в зависимости от значение *lock* безопасная от процесса обертка синхронизации может быть возвращенный вместо сырья ctypes объект. Если *lock* равно `True` (по умолчанию), создается новый объект блокировки для синхронизации доступа к значение. Если *lock* является объектом [`Lock`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Lock "multiprocessing.Lock") или [`RLock`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.RLock "multiprocessing.RLock"), то это будет используемый для синхронизации доступа к значение. Если *lock* будет `False` тогда, то доступ к объекту возвращенный не будет автоматически защищен замком, таким образом, это не обязательно будет «безопасно от процесса». Обратите внимание, что *lock* является только ключевым аргументом. `multiprocessing.sharedctypes.``copy`(*obj*)[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.sharedctypes.copy "Ссылка на это определение") Возвращает объект ctypes, выделенный из общей памяти, который является копией объекта ctypes *obj*. `multiprocessing.sharedctypes.``synchronized`(*obj*\[, *lock*\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.sharedctypes.synchronized "Ссылка на это определение") Возвращает безопасный для процесса объект-обертка для объекта ctypes, который использует *lock* для синхронизации доступа. Если *lock* имеет значение `None` (по умолчанию), то объект [`multiprocessing.RLock`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.RLock "multiprocessing.RLock") создается автоматически. Синхронизированная обертка будет иметь два метода в дополнение к методам обертываемого объекта: `get_obj()` возвращает обертываемый объект и `get_lock()` возвращает блокируемый объект используемый для синхронизации. Обратите внимание, что доступ к объекту ctypes через оболочку может быть намного медленнее, чем доступ к объекту raw ctypes. Изменено в версии 3.5: Синхронизированные объекты поддерживают протокол [менеджера контекста](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/glossary.html#term-22). В приведенной ниже таблице сравнивается синтаксис создания общих объектов ctypes из общей памяти с синтаксисом обычных ctypes. (В таблице `MyStruct` представлена некоторая подкласс [`ctypes.Structure`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/ctypes.html#ctypes.Structure "ctypes.Structure"). | ctypes | sharedctypes используя тип | sharedctypes используя typecode | |---|---|---| | c\_double(2.4) | RawValue(c\_double, 2.4) | RawValue(„d“, 2.4) | | MyStruct(4, 6) | RawValue(MyStruct, 4, 6) | | | (c\_short \* 7)() | RawArray(c\_short, 7) | RawArray(„h“, 7) | | (c\_int \* 3)(9, 2, 8) | RawArray(c\_int, (9, 2, 8)) | RawArray(„i“, (9, 2, 8)) | Ниже приведен пример, когда ряд объектов ctypes изменяется дочерним процессом: ``` from multiprocessing import Process, Lock from multiprocessing.sharedctypes import Value, Array from ctypes import Structure, c_double class Point(Structure): _fields_ = [('x', c_double), ('y', c_double)] def modify(n, x, s, A): n.value **= 2 x.value **= 2 s.value = s.value.upper() for a in A: a.x **= 2 a.y **= 2 if __name__ == '__main__': lock = Lock() n = Value('i', 7) x = Value(c_double, 1.0/3.0, lock=False) s = Array('c', b'hello world', lock=lock) A = Array(Point, [(1.875,-6.25), (-5.75,2.0), (2.375,9.5)], lock=lock) p = Process(target=modify, args=(n, x, s, A)) p.start() p.join() print(n.value) print(x.value) print(s.value) print([(a.x, a.y) for a in A]) ``` Результаты напечатаны: ``` 49 0.1111111111111111 HELLO WORLD [(3.515625, 39.0625), (33.0625, 4.0), (5.640625, 90.25)] ``` ### Менеджеры[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-managers "Ссылка на этот заголовок") Менеджеры предоставляют способ создания данных, которые могут совместно использоваться различными процессами, включая совместное использование по сети между процессами, работающими на разных машинах. Объект-менеджер управляет серверным процессом, который управляет *shared objects*. Другие процессы могут обращаться к общим объектам с помощью прокси. `multiprocessing.``Manager`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.sharedctypes.multiprocessing.Manager "Ссылка на это определение") Возвращает начатый объект [`SyncManager`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.SyncManager "multiprocessing.managers.SyncManager"), который может быть используемый для разделения объектов между процессами. Объект менеджера возвращенный соответствует порожденному дочернему процессу и имеет методы, которые создадут общие объекты и соответствующие возвращаемое прокси. Процессы менеджера будут остановлены сразу после сбора мусора или завершения родительского процесса. Классы менеджера определяются в модуле [`multiprocessing.managers`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing.managers "multiprocessing.managers: Обмен данными между процессами с общими объектами."): *class* `multiprocessing.managers.``BaseManager`(\[*address*\[, *authkey*\]\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.BaseManager "Ссылка на это определение") Создайте объект BaseManager. После создания необходимо вызвать [`start()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.BaseManager.start "multiprocessing.managers.BaseManager.start") или `get_server().serve_forever()`, чтобы гарантировать, что объект менеджера ссылается на запущенный процесс менеджера. *address* - адрес, по которому процесс менеджера прослушивает новые подключения. Если *address* `None`, то выбирается произвольная. *authkey* - ключ идентификации, который будет используемый, чтобы проверить законность поступающих связей с процессом сервера. Если *authkey* - `None` тогда, `current_process().authkey` - используемый. В противном случае *authkey* является используемый и должен быть байтом строка. `start`(\[*initializer*\[, *initargs*\]\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.BaseManager.start "Ссылка на это определение") Начните подпроцессы, чтобы начать менеджера. Если *initializer* не является `None`, то подпроцессы вызовет `initializer(*initargs)` при запуске. `get_server`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.BaseManager.get_server "Ссылка на это определение") Возвращает объект `Server`, представляющий фактический сервер под управлением менеджера. Объект `Server` поддерживает метод `serve_forever()`: \>\>\> ``` >>> from multiprocessing.managers import BaseManager >>> manager = BaseManager(address=('', 50000), authkey=b'abc') >>> server = manager.get_server() >>> server.serve_forever() ``` `Server` дополнительно содержит [`address`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.BaseManager.address "multiprocessing.managers.BaseManager.address") атрибут. `connect`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.BaseManager.connect "Ссылка на это определение") Подключить объект локального менеджера к процессу удаленного менеджера: \>\>\> ``` >>> from multiprocessing.managers import BaseManager >>> m = BaseManager(address=('127.0.0.1', 50000), authkey=b'abc') >>> m.connect() ``` `shutdown`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.BaseManager.shutdown "Ссылка на это определение") Остановить процесс используемый менеджером. Это только доступно, если [`start()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.BaseManager.start "multiprocessing.managers.BaseManager.start") был используемый, чтобы начать процесс сервера. Это можно вызвать несколько раз. `register`(*typeid*\[, *callable*\[, *proxytype*\[, *exposed*\[, *method\_to\_typeid*\[, *create\_method*\]\]\]\]\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.BaseManager.register "Ссылка на это определение") classmethod, который может быть используемый для регистрации типа или подлежащий выкупу с классом менеджера. *typeid* - «идентификатор типа», который является используемый, чтобы определить особый тип общего объекта. Это должно быть строка. *callable* является вызываемым используемый для создания объектов для этого идентификатора типа. Если диспетчер сущность будет подключен к серверу с помощью метода [`connect()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.BaseManager.connect "multiprocessing.managers.BaseManager.connect") или если аргумент *create\_method* имеет значение `False`, его можно оставить как `None`. *proxytype* является подкласс [`BaseProxy`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.BaseProxy "multiprocessing.managers.BaseProxy"), который используемый для создания прокси для общих объектов с этим *typeid*. Если `None`, то класс прокси создается автоматически. *exposed* - используемый, чтобы определить последовательность вызова метода, которые прокси для этого typeid нужно разрешить доступу, используя [`BaseProxy._callmethod()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.BaseProxy._callmethod "multiprocessing.managers.BaseProxy._callmethod"). (Если *exposed* - `None` тогда, `proxytype._exposed_` - используемый вместо этого, если он существует.) в случае, если не указан список разоблаченных объектов, будут доступны все «публичные методы» общего объекта. (Здесь «метод публичный» означает любой атрибут, у которого есть метод [`__call__()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/reference/datamodel.html#object.__call__ "object.__call__") и чьё имя не начинается с `'_'`.) *method\_to\_typeid* - отображение используемый, чтобы определить тип возвращает тех выставленных методов, которые должны возвращает прокси. Это наносит на карту названия метода к typeid строки. (Если *method\_to\_typeid* - `None` тогда, `proxytype._method_to_typeid_` - используемый вместо этого, если он существует.) Если вызов метода не будет ключом этого отображения или если отображение будет `None` тогда объект, то возвращенный методом будет скопирован значение. *create\_method* определяет, должен ли метод быть создан с именем *typeid*, который может быть используемый, чтобы сказать процессу сервера создавать новый общий объект и возвращает прокси для него. По умолчанию это значение равно `True`. [`BaseManager`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.BaseManager "multiprocessing.managers.BaseManager") сущности также имеют одно свойство только для чтения: `address`[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.BaseManager.address "Ссылка на это определение") Адрес, используемый менеджером. Изменено в версии 3.3: Объекты менеджера поддерживают протокол управления контекст - см. раздел [Типы менеджера контекста](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/stdtypes.html#typecontextmanager). [`__enter__()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/stdtypes.html#contextmanager.__enter__ "contextmanager.__enter__") запускает процесс сервера (если он еще не запущен), а затем возвращает объект диспетчера. [`__exit__()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/stdtypes.html#contextmanager.__exit__ "contextmanager.__exit__") вызовы [`shutdown()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.BaseManager.shutdown "multiprocessing.managers.BaseManager.shutdown"). В предыдущих версиях [`__enter__()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/stdtypes.html#contextmanager.__enter__ "contextmanager.__enter__") не запускал серверный процесс диспетчера, если он еще не был запущен. *class* `multiprocessing.managers.``SyncManager`[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.SyncManager "Ссылка на это определение") Подкласс [`BaseManager`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.BaseManager "multiprocessing.managers.BaseManager"), который может быть используемый для синхронизации процессов. Объекты этого типа возвращенный `multiprocessing.Manager()`. Его методы обычно создают и возвращает [Прокси объекты](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-proxy-objects) для многих типы данных используемый, которые будут синхронизированы через процессы. Это, в частности, включает общие списки и словари. `Barrier`(*parties*\[, *action*\[, *timeout*\]\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.SyncManager.Barrier "Ссылка на это определение") Создание общего объекта [`threading.Barrier`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.Barrier "threading.Barrier") и возвращает прокси для него. Добавлено в версии 3.3. `BoundedSemaphore`(\[*value*\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.SyncManager.BoundedSemaphore "Ссылка на это определение") Создание общего объекта [`threading.BoundedSemaphore`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.BoundedSemaphore "threading.BoundedSemaphore") и возвращает прокси для него. `Condition`(\[*lock*\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.SyncManager.Condition "Ссылка на это определение") Создание общего объекта [`threading.Condition`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.Condition "threading.Condition") и возвращает прокси для него. Если задано значение *lock*, то оно должно быть прокси для объекта [`threading.Lock`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.Lock "threading.Lock") или [`threading.RLock`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.RLock "threading.RLock"). Изменено в версии 3.3: Добавлен метод [`wait_for()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.Condition.wait_for "threading.Condition.wait_for"). `Event`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.SyncManager.Event "Ссылка на это определение") Создание общего объекта [`threading.Event`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.Event "threading.Event") и возвращает прокси для него. `Lock`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.SyncManager.Lock "Ссылка на это определение") Создание общего объекта [`threading.Lock`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.Lock "threading.Lock") и возвращает прокси для него. `Namespace`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.SyncManager.Namespace "Ссылка на это определение") Создание общего объекта [`Namespace`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.Namespace "multiprocessing.managers.Namespace") и возвращает прокси для него. `Queue`(\[*maxsize*\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.SyncManager.Queue "Ссылка на это определение") Создание общего объекта [`queue.Queue`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/queue.html#queue.Queue "queue.Queue") и возвращает прокси для него. `RLock`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.SyncManager.RLock "Ссылка на это определение") Создание общего объекта [`threading.RLock`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.RLock "threading.RLock") и возвращает прокси для него. `Semaphore`(\[*value*\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.SyncManager.Semaphore "Ссылка на это определение") Создание общего объекта [`threading.Semaphore`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#threading.Semaphore "threading.Semaphore") и возвращает прокси для него. `Array`(*typecode*, *sequence*)[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.SyncManager.Array "Ссылка на это определение") Создайте массив и возвращает прокси-сервер для него. `Value`(*typecode*, *value*)[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.SyncManager.Value "Ссылка на это определение") Создайте объект с возможностью записи `value` атрибут и возвращает прокси для него. `dict`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.SyncManager.dict "Ссылка на это определение") `dict`(*mapping*) `dict`(*sequence*) Создание общего объекта [`dict`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.SyncManager.dict "multiprocessing.managers.SyncManager.dict") и возвращает прокси для него. `list`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.SyncManager.list "Ссылка на это определение") `list`(*sequence*) Создание общего объекта [`list`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/stdtypes.html#list "list") и возвращает прокси для него. Изменено в версии 3.6: Общие объекты могут быть вложены. Например, объект общего контейнера, такой как общий список, может содержать другие общие объекты, которые будут управляться и синхронизироваться [`SyncManager`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.SyncManager "multiprocessing.managers.SyncManager"). *class* `multiprocessing.managers.``Namespace`[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.Namespace "Ссылка на это определение") Тип, который может регистрироваться в [`SyncManager`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.SyncManager "multiprocessing.managers.SyncManager"). Объект пространства имен не имеет публичных методов, но содержит записываемые атрибуты. Его представление показывает значения его атрибутов. Однако при использовании прокси для объекта пространства имен атрибут, начинающийся с `'_'`, будет атрибут прокси, а не атрибут ссылки: \>\>\> ``` >>> manager = multiprocessing.Manager() >>> Global = manager.Namespace() >>> Global.x = 10 >>> Global.y = 'hello' >>> Global._z = 12.3 # это атрибут прокси >>> print(Global) Namespace(x=10, y='hello') ``` #### Настраиваемые менеджеры[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id14 "Ссылка на этот заголовок") Для создания собственного менеджера создается подкласс [`BaseManager`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.BaseManager "multiprocessing.managers.BaseManager") и используется классметод [`register()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.BaseManager.register "multiprocessing.managers.BaseManager.register") для регистрации новых типов или вызываемых объектов в классе менеджера. Например: ``` from multiprocessing.managers import BaseManager class MathsClass: def add(self, x, y): return x + y def mul(self, x, y): return x * y class MyManager(BaseManager): pass MyManager.register('Maths', MathsClass) if __name__ == '__main__': with MyManager() as manager: maths = manager.Maths() print(maths.add(4, 3)) # prints 7 print(maths.mul(7, 8)) # prints 56 ``` #### Использование удаленного менеджера[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id15 "Ссылка на этот заголовок") Можно запускать сервер менеджера на одной машине и использовать его клиентами с других машин (при условии, что соответствующие брандмауэры разрешают это). Выполнение следующих команд создает сервер для одной общей очереди, к которой могут иметь доступ удаленные клиенты: \>\>\> ``` >>> from multiprocessing.managers import BaseManager >>> from queue import Queue >>> queue = Queue() >>> class QueueManager(BaseManager): pass >>> QueueManager.register('get_queue', callable=lambda:queue) >>> m = QueueManager(address=('', 50000), authkey=b'abracadabra') >>> s = m.get_server() >>> s.serve_forever() ``` Один клиент может получить доступ к серверу следующим образом: \>\>\> ``` >>> from multiprocessing.managers import BaseManager >>> class QueueManager(BaseManager): pass >>> QueueManager.register('get_queue') >>> m = QueueManager(address=('foo.bar.org', 50000), authkey=b'abracadabra') >>> m.connect() >>> queue = m.get_queue() >>> queue.put('hello') ``` Его также может использовать другой клиент: \>\>\> ``` >>> from multiprocessing.managers import BaseManager >>> class QueueManager(BaseManager): pass >>> QueueManager.register('get_queue') >>> m = QueueManager(address=('foo.bar.org', 50000), authkey=b'abracadabra') >>> m.connect() >>> queue = m.get_queue() >>> queue.get() 'hello' ``` Локальные процессы также могут обращаться к этой очереди, используя код сверху на клиенте для удаленного доступа к ней: \>\>\> ``` >>> from multiprocessing import Process, Queue >>> from multiprocessing.managers import BaseManager >>> class Worker(Process): ... def __init__(self, q): ... self.q = q ... super(Worker, self).__init__() ... def run(self): ... self.q.put('local hello') ... >>> queue = Queue() >>> w = Worker(queue) >>> w.start() >>> class QueueManager(BaseManager): pass ... >>> QueueManager.register('get_queue', callable=lambda: queue) >>> m = QueueManager(address=('', 50000), authkey=b'abracadabra') >>> s = m.get_server() >>> s.serve_forever() ``` ### Прокси объекты[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-proxy-objects "Ссылка на этот заголовок") Прокси - объект, какой *относится* к общему объекту, который живет (по- видимому), в другом процессе. Говорят, что общий объект является *ссылкой* прокси. Несколько прокси-объектов могут иметь один и тот же ссылочный объект. Прокси-объект содержат методы, которые вызывают соответствующие методы его ссылки (хотя не каждый метод ссылки обязательно будет доступен через прокси). Таким образом, прокси может быть используемый так же, как его референт: \>\>\> ``` >>> from multiprocessing import Manager >>> manager = Manager() >>> l = manager.list([i*i for i in range(10)]) >>> print(l) [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>> print(repr(l)) <ListProxy object, typeid 'list' at 0x...> >>> l[4] 16 >>> l[2:5] [4, 9, 16] ``` Заметьте, что применение `str()` прокси будет возвращает представление референта, тогда как применение [`repr()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/functions.html#repr "repr") будет возвращает представление прокси. Важной особенностью прокси-объектов является то, что они могут быть переданы между процессами. Таким образом, референт может содержать [Прокси объекты](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-proxy-objects). Это разрешает вложение этих управляемых списков, словари и другого [Прокси объекты](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-proxy-objects): \>\>\> ``` >>> a = manager.list() >>> b = manager.list() >>> a.append(b) # ссылка a теперь содержит ссылку b >>> print(a, b) [<ListProxy object, typeid 'list' at ...>] [] >>> b.append('hello') >>> print(a[0], b) ['hello'] ['hello'] ``` Аналогично, прокси словарь и списка могут быть вложены друг в друга: \>\>\> ``` >>> l_outer = manager.list([ manager.dict() for i in range(2) ]) >>> d_first_inner = l_outer[0] >>> d_first_inner['a'] = 1 >>> d_first_inner['b'] = 2 >>> l_outer[1]['c'] = 3 >>> l_outer[1]['z'] = 26 >>> print(l_outer[0]) {'a': 1, 'b': 2} >>> print(l_outer[1]) {'c': 3, 'z': 26} ``` Если стандартные (не прокси) [`list`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/stdtypes.html#list "list") или `dict` объекты содержатся в ссылке, изменения этих изменяемых значения не будут распространяться через менеджер, поскольку прокси не может знать, когда изменятся содержащиеся в них значения. Однако хранение значение в контейнерном прокси (который вызывает `__setitem__` на объекте по доверенности) действительно размножается через менеджера и так эффективно изменить такой предмет, можно было повторно назначить измененный значение контейнерному прокси: ``` # создать список прокси и добавить изменяемый объект (словарь) lproxy = manager.list() lproxy.append({}) # теперь изменяемый словарь d = lproxy[0] d['a'] = 1 d['b'] = 2 # на этом этапе изменения d еще не синхронизируются, но при обновлении словаря # прокси уведомляется об изменении lproxy[0] = d ``` Этот подход, возможно, менее удобен, чем использование вложенных [Прокси объекты](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-proxy-objects) в большинстве случаев использования, но также демонстрирует уровень управления синхронизацией. Примечание Прокси-типы в [`multiprocessing`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing "multiprocessing: Процессный параллелизм.") не поддерживают сравнения по значение. Итак, для сущность у нас есть: \>\>\> ``` >>> manager.list([1,2,3]) == [1,2,3] False ``` Вместо этого следует использовать копию ссылки при проведении сравнений. *class* `multiprocessing.managers.``BaseProxy`[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.BaseProxy "Ссылка на это определение") Объекты по доверенности - сущности подклассы [`BaseProxy`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.BaseProxy "multiprocessing.managers.BaseProxy"). `_callmethod`(*methodname*\[, *args*\[, *kwds*\]\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.BaseProxy._callmethod "Ссылка на это определение") Вызов и возвращает результата метода ссылки прокси. Если `proxy` - прокси, ссылочным элементом которого является `obj`, то выражение: ``` proxy._callmethod(methodname, args, kwds) ``` вычислит выражение: ``` getattr(obj, methodname)(*args, **kwds) ``` в процессе менеджере. возвращенный значение будет копией результата вызова или прокси для нового общего объекта - см. документацию для аргумента *method\_to\_typeid* [`BaseManager.register()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.BaseManager.register "multiprocessing.managers.BaseManager.register"). Если в результате вызова возникает исключение, то вызов повторно инициируется функцией [`_callmethod()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.BaseProxy._callmethod "multiprocessing.managers.BaseProxy._callmethod"). Если в процессе менеджера возникает другое исключение, оно преобразуется в исключение `RemoteError` и инициируется [`_callmethod()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.BaseProxy._callmethod "multiprocessing.managers.BaseProxy._callmethod"). Обратите внимание, в частности, на то, что исключение будет создано, если *methodname* не было *exposed*. Пример использования [`_callmethod()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.BaseProxy._callmethod "multiprocessing.managers.BaseProxy._callmethod"): \>\>\> ``` >>> l = manager.list(range(10)) >>> l._callmethod('__len__') 10 >>> l._callmethod('__getitem__', (slice(2, 7),)) # equivalent to l[2:7] [2, 3, 4, 5, 6] >>> l._callmethod('__getitem__', (20,)) # equivalent to l[20] Traceback (most recent call last): ... IndexError: list index out of range ``` `_getvalue`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.BaseProxy._getvalue "Ссылка на это определение") Возвращает копию референта. Если референт не может быть выбран, это вызовет исключение. `__repr__`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.BaseProxy.__repr__ "Ссылка на это определение") Возвращает представление прокси-объекта. `__str__`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.managers.BaseProxy.__str__ "Ссылка на это определение") Возвращает представление референта. #### Очистка[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id17 "Ссылка на этот заголовок") Объект по доверенности использует weakref колбэк так, чтобы, когда это собрало мусор, он вычеркнул из списка себя от менеджера, который владеет его референтом. Общий объект удаляется из процесса диспетчера, если на него больше не ссылается ни один прокси. ### Процессные пулы[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing.pool "Ссылка на этот заголовок") Можно создать пул процессов, который будет выполнять задачи, переданные ему с классом [`Pool`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool "multiprocessing.pool.Pool"). *class* `multiprocessing.pool.``Pool`(\[*processes*\[, *initializer*\[, *initargs*\[, *maxtasksperchild*\[, *context*\]\]\]\]\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool "Ссылка на это определение") Объект пула процессов, который управляет пулом рабочих процессов, в который могут отправляться задания. Он поддерживает асинхронные результаты с тайм-аутами и колбэки и имеет параллельную реализацию карты. *processes* - количество используемых рабочих процессов. Если *processes* `None`, то число возвращенный по [`os.cpu_count()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/os.html#os.cpu_count "os.cpu_count") равно используемый. Если *initializer* не является `None`, то каждый рабочий процесс будет вызывать `initializer(*initargs)` при запуске. *maxtasksperchild* - количество задач, которые рабочий процесс может выполнить до выхода и замены новым рабочим процессом для освобождения неиспользуемых ресурсов. Дефолт *maxtasksperchild* - `None`, что означает процессы рабочего, будет жить пока бассейн. *context* может быть используемый, чтобы определить контекст используемый для старта процессов рабочего. Обычно пул создается с помощью функции `multiprocessing.Pool()` или метода [`Pool()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool "multiprocessing.pool.Pool") объекта контекст. В обоих случаях *context* устанавливается соответствующим образом. Следует отметить, что методы объекта пула должны вызываться только процессом, создавшим пул. Предупреждение [`multiprocessing.pool`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing.pool "multiprocessing.pool: Создать пулы процессов.") объекты имеют внутренние ресурсы, которыми необходимо правильно управлять (как и любой другой ресурс), используя пул в качестве менеджера контекст или вызывая [`close()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.close "multiprocessing.pool.Pool.close") и [`terminate()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.terminate "multiprocessing.pool.Pool.terminate") вручную. Неспособность сделать это может привести к зависанию процесса при завершении. Обратите внимание, что это **не верно**, чтобы полагаться на сборщик мусора, чтобы уничтожить пул, так как CPython не гарантирует, что финализатор пула будет вызван (см. [`object.__del__()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/reference/datamodel.html#object.__del__ "object.__del__") для получения дополнительной информации). Добавлено в версии 3.2: *maxtasksperchild* Добавлено в версии 3.4: *context* Примечание Рабочие процессы внутри [`Pool`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool "multiprocessing.pool.Pool") обычно работают в течение всей продолжительности рабочей очереди пула. Частый шаблон, встречающийся в других системах (таких как Apache, mod\_wsgi и т.д.) для освобождения ресурсов, находящихся в распоряжении работников, заключается в том, чтобы позволить работнику в пуле выполнить только определенный объем работы перед выходом, очисткой и новым процессом, который должен заменить старый. Аргумент *maxtasksperchild* [`Pool`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool "multiprocessing.pool.Pool") предоставляет эту возможность конечному пользователю. `apply`(*func*\[, *args*\[, *kwds*\]\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.apply "Ссылка на это определение") Вызовите *func* с аргументами *args* и ключевой аргументы *kwds*. Он блокируется до тех пор, пока результат не будет готов. Учитывая эти блоки, [`apply_async()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.apply_async "multiprocessing.pool.Pool.apply_async") лучше подходит для выполнения работы параллельно. Кроме того, *func* выполняется только в одном из работников пула. `apply_async`(*func*\[, *args*\[, *kwds*\[, *callback*\[, *error\_callback*\]\]\]\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.apply_async "Ссылка на это определение") Вариант метода [`apply()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.apply "multiprocessing.pool.Pool.apply"), который возвращает объект [`AsyncResult`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.AsyncResult "multiprocessing.pool.AsyncResult"). Если задан параметр *callback*, то он должен быть вызываемым и принимать один аргумент. То, когда результат становится готовым *callback*, применено к нему, это - то, если неудавшееся требование, в этом случае *error\_callback* не применен вместо этого. Если задан параметр *error\_callback*, то он должен быть вызываемым и принимать один аргумент. Если целевая функция терпит неудачу, то *error\_callback* называют за исключением сущность. Обратные вызовы должны быть завершены немедленно, поскольку в противном случае поток, обрабатывающая результаты, будет заблокирована. `map`(*func*, *iterable*\[, *chunksize*\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.map "Ссылка на это определение") Параллельный эквивалент встроенной функции [`map()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/functions.html#map "map") (однако он поддерживает только один аргумент *iterable* для нескольких итерабелей см. [`starmap()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.starmap "multiprocessing.pool.Pool.starmap")). Он блокируется до тех пор, пока результат не будет готов. Этот метод разбивает итабль на несколько чанки, которые он передает в пул процессов как отдельные задачи. (Приблизительный) размер этих чанки можно задать, установив для параметра *chunksize* положительное целое число. Обратите внимание, что это может привести к интенсивному использованию памяти для очень длинных итераблей. Рассмотрите возможность использования [`imap()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.imap "multiprocessing.pool.Pool.imap") или [`imap_unordered()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.imap_unordered "multiprocessing.pool.Pool.imap_unordered") с явным параметром *chunksize* для повышения эффективности. `map_async`(*func*, *iterable*\[, *chunksize*\[, *callback*\[, *error\_callback*\]\]\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.map_async "Ссылка на это определение") Вариант метода [`map()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.map "multiprocessing.pool.Pool.map"), который возвращает объект [`AsyncResult`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.AsyncResult "multiprocessing.pool.AsyncResult"). Если задан параметр *callback*, то он должен быть вызываемым и принимать один аргумент. То, когда результат становится готовым *callback*, применено к нему, это - то, если неудавшееся требование, в этом случае *error\_callback* не применен вместо этого. Если задан параметр *error\_callback*, то он должен быть вызываемым и принимать один аргумент. Если целевая функция терпит неудачу, то *error\_callback* называют за исключением сущность. Обратные вызовы должны быть завершены немедленно, поскольку в противном случае поток, обрабатывающая результаты, будет заблокирована. `imap`(*func*, *iterable*\[, *chunksize*\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.imap "Ссылка на это определение") Более ленивый вариант [`map()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.map "multiprocessing.pool.Pool.map"). Аргумент *chunksize* совпадает с аргументом используемый методом [`map()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.map "multiprocessing.pool.Pool.map"). Очень долго iterables использование большого значение для *chunksize* может заставить работу закончить **гораздо** быстрее, чем использование дефолта значение `1`. Также если *chunksize* является `1`, то метод `next()` итератора возвращенный методом [`imap()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.imap "multiprocessing.pool.Pool.imap") имеет необязательный параметр *timeout*: `next(timeout)` поднимет [`multiprocessing.TimeoutError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.TimeoutError "multiprocessing.TimeoutError"), если результат не может быть возвращенный в течение *timeout* секунд. `imap_unordered`(*func*, *iterable*\[, *chunksize*\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.imap_unordered "Ссылка на это определение") То же как [`imap()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.imap "multiprocessing.pool.Pool.imap") за исключением того, что заказ результатов возвращенный iterator нужно считать произвольным. (Только при наличии только одного рабочего процесса порядок гарантирован как «правильный». `starmap`(*func*, *iterable*\[, *chunksize*\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.starmap "Ссылка на это определение") Как [`map()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/functions.html#map "map") за исключением того, что элементы *iterable*, как ожидают, будут iterables, которые распакованы как аргументы. Следовательно *iterable* `[(1,2), (3, 4)]` приводит к `[func(1,2), func(3,4)]`. Добавлено в версии 3.3. `starmap_async`(*func*, *iterable*\[, *chunksize*\[, *callback*\[, *error\_callback*\]\]\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.starmap_async "Ссылка на это определение") Комбинация [`starmap()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.starmap "multiprocessing.pool.Pool.starmap") и [`map_async()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.map_async "multiprocessing.pool.Pool.map_async"), которая итерирует по *iterable* итераблей и вызывает *func* с итераблями распакованными. Возвращает объект результата. Добавлено в версии 3.3. `close`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.close "Ссылка на это определение") Запрещает отправку дополнительных задач в пул. После завершения всех задач рабочие процессы завершаются. `terminate`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.terminate "Ссылка на это определение") Немедленная остановка рабочих процессов без завершения незавершенной работы. То, когда объект бассейна - мусор, собралось, [`terminate()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.terminate "multiprocessing.pool.Pool.terminate") немедленно назовут. `join`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.join "Ссылка на это определение") Дождитесь завершения рабочих процессов. Перед использованием [`close()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.close "multiprocessing.pool.Pool.close") необходимо вызвать [`terminate()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.terminate "multiprocessing.pool.Pool.terminate") или [`join()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.join "multiprocessing.pool.Pool.join"). Добавлено в версии 3.3: Объекты пула теперь поддерживают протокол управления контекст - см. раздел [Типы менеджера контекста](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/stdtypes.html#typecontextmanager). [`__enter__()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/stdtypes.html#contextmanager.__enter__ "contextmanager.__enter__") возвращает объект пула, [`__exit__()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/stdtypes.html#contextmanager.__exit__ "contextmanager.__exit__") вызывает [`terminate()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.terminate "multiprocessing.pool.Pool.terminate"). *class* `multiprocessing.pool.``AsyncResult`[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.AsyncResult "Ссылка на это определение") Класс результата возвращенный по [`Pool.apply_async()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.apply_async "multiprocessing.pool.Pool.apply_async") и [`Pool.map_async()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.map_async "multiprocessing.pool.Pool.map_async"). `get`(\[*timeout*\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.AsyncResult.get "Ссылка на это определение") Возвращает результат при его поступлении. Если *timeout* не является `None` и результат не поступает в течение *timeout* секунд, то [`multiprocessing.TimeoutError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.TimeoutError "multiprocessing.TimeoutError") поднимается. Если удаленное требование подняло исключение тогда, что исключение будет повторно поднято [`get()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.AsyncResult.get "multiprocessing.pool.AsyncResult.get"). `wait`(\[*timeout*\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.AsyncResult.wait "Ссылка на это определение") Подождите, пока результат будет доступен, или до истечения *timeout* секунд. `ready`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.AsyncResult.ready "Ссылка на это определение") Возвращает, завершен ли вызов. `successful`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.AsyncResult.successful "Ссылка на это определение") Возвращает, выполнен ли вызов без возникновения исключения. Поднимет [`ValueError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#ValueError "ValueError"), если результат не готов. Изменено в версии 3.7: Если результат не готов, [`ValueError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#ValueError "ValueError") поднимается вместо [`AssertionError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#AssertionError "AssertionError"). В следующем примере показано использование пула: ``` from multiprocessing import Pool import time def f(x): return x*x if __name__ == '__main__': with Pool(processes=4) as pool: # запустить 4 процесса воркера result = pool.apply_async(f, (10,)) # асинхронно вычислить "f(10)" в одном процессе print(result.get(timeout=1)) # печатает "100", если только ваш компьютер не работает *очень* медленно print(pool.map(f, range(10))) # печать "[0, 1, 4,..., 81]" it = pool.imap(f, range(10)) print(next(it)) # печать "0" print(next(it)) # печать "1" print(it.next(timeout=1)) # печать "4" если ваш компьютер не *очень* медленный result = pool.apply_async(time.sleep, (10,)) print(result.get(timeout=1)) # поднять multiprocessing.TimeoutError ``` ### Слушатели и клиенты[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing.connection "Ссылка на этот заголовок") Обычно сообщение, проходящее между процессами, сделано, используя очереди, или при помощи [`Connection`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Connection "multiprocessing.connection.Connection") возражает возвращенный [`Pipe()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Pipe "multiprocessing.Pipe"). Однако модуль [`multiprocessing.connection`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing.connection "multiprocessing.connection: API для работы с сокетами.") обеспечивает некоторую гибкость. Он в основном дает высокоуровневый ориентированный на сообщения API для работы с сокеты или Windows с именем пайпы. У этого также есть поддержка *digest authentication*, используя модуль [`hmac`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/hmac.html#module-hmac "hmac: Реализация ключевого хеширования для аутентификации сообщений (HMAC)"), и опроса многочисленных связей одновременно. `multiprocessing.connection.``deliver_challenge`(*connection*, *authkey*)[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.deliver_challenge "Ссылка на это определение") Отправка случайно сгенерированного сообщения на другой конец соединения и ожидание ответа. Если ответ соответствует дайджесту сообщения с использованием клавиши *authkey*, то приветственное сообщение отправляется на другой конец соединения. В противном случае поднимается [`AuthenticationError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.AuthenticationError "multiprocessing.AuthenticationError"). `multiprocessing.connection.``answer_challenge`(*connection*, *authkey*)[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.answer_challenge "Ссылка на это определение") Получение сообщения, вычисление дайджеста сообщения с использованием *authkey* в качестве ключа, а затем отправка дайджеста обратно. Если приветственное сообщение не получено, возникает сообщение [`AuthenticationError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.AuthenticationError "multiprocessing.AuthenticationError"). `multiprocessing.connection.``Client`(*address*\[, *family*\[, *authkey*\]\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Client "Ссылка на это определение") Попытка установить соединение с прослушивателем, который использует адрес *address*, возвращая [`Connection`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Connection "multiprocessing.connection.Connection"). Тип соединения определяется аргументом *family*, но обычно его можно опустить, поскольку его обычно можно вывести из формата *address*. (См. [Форматы адреса](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-address-formats)) Если *authkey* задан, а не None, он должен быть байтом строка и будет используемый в качестве секретного ключа для вызова аутентификации на основе HMAC. Аутентификация не выполняется, если *authkey* является None. [`AuthenticationError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.AuthenticationError "multiprocessing.AuthenticationError") возникает в случае сбоя аутентификации. См. [Ключи аутентификации](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-auth-keys). *class* `multiprocessing.connection.``Listener`(\[*address*\[, *family*\[, *backlog*\[, *authkey*\]\]\]\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Listener "Ссылка на это определение") Обертка для связанной сокет или Windows с именем пайп, которая «слушает» подключения. *address* - адрес, который должен быть используемый связанным сокет или именованным пайп объекта прослушивателя. Примечание Если адрес „0.0.0.0“ будет используемый, то адрес не будет соединяемой конечной точкой на Windows. Если требуется соединяемая конечная точка, следует использовать „127.0.0.1“. *family* - тип используемого сокет (или именованного пайп). Это может быть один из строки `'AF_INET'` (для TCP сокет), `'AF_UNIX'` (для домена Unix сокет) или `'AF_PIPE'` (для Windows с именем пайп). Из них только первый гарантированно доступен. Если *family* `None`, то семейство выводится из формата *address*. Если *address* также является `None`, то выбирается значение по умолчанию. Это семейство по умолчанию считается самым быстрым из доступных. См. [Форматы адреса](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-address-formats). Обратите внимание, что если *family* является `'AF_UNIX'` и адрес `None`, то сокет будет создан в частном временном каталоге, созданном с помощью [`tempfile.mkstemp()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/tempfile.html#tempfile.mkstemp "tempfile.mkstemp"). Если объект прослушивателя использует сокет, то *backlog* (по умолчанию 1) передается методу [`listen()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/socket.html#socket.socket.listen "socket.socket.listen") сокет после его привязки. Если *authkey* задан, а не None, он должен быть байтом строка и будет используемый в качестве секретного ключа для вызова аутентификации на основе HMAC. Аутентификация не выполняется, если *authkey* является None. [`AuthenticationError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.AuthenticationError "multiprocessing.AuthenticationError") возникает в случае сбоя аутентификации. См. [Ключи аутентификации](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-auth-keys). `accept`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Listener.accept "Ссылка на это определение") Принять подключение на связанном сокете или именованный пайп объекта слушателя и возвращает объект [`Connection`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Connection "multiprocessing.connection.Connection"). Если идентификация предпринята и терпит неудачу, то поднимается [`AuthenticationError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.AuthenticationError "multiprocessing.AuthenticationError"). `close`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Listener.close "Ссылка на это определение") Закрыть связанный сокет или именованный пайп объекта слушателя. Это вызывается автоматически при сборе мусора прослушивателя. Однако желательно называть его явно. Объекты прослушивателя имеют следующие свойства только для чтения: `address`[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Listener.address "Ссылка на это определение") Адрес, используемый объектом Listener. `last_accepted`[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Listener.last_accepted "Ссылка на это определение") Адрес, с которого пришло последнее принятое соединение. Если это недоступно, то это `None`. Добавлено в версии 3.3: Объекты прослушивателя теперь поддерживают протокол управления контекст - см. раздел [Типы менеджера контекста](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/stdtypes.html#typecontextmanager). [`__enter__()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/stdtypes.html#contextmanager.__enter__ "contextmanager.__enter__") возвращает объект прослушивателя, а [`__exit__()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/stdtypes.html#contextmanager.__exit__ "contextmanager.__exit__") вызывает [`close()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Listener.close "multiprocessing.connection.Listener.close"). `multiprocessing.connection.``wait`(*object\_list*, *timeout=None*)[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.wait "Ссылка на это определение") Подождите, пока объект в *object\_list* будет готов. Возвращает список тех объектов в *object\_list*, которые готовы. Если *timeout* является float, то вызов блокируется максимум на столько секунд. Если *timeout* будет `None` тогда, то он заблокирует в течение неограниченного периода. Отрицательное время ожидания эквивалентно нулевому времени ожидания. Как для Unix, так и для Windows объект может отображаться в *object\_list*, если это так - читаемый объект [`Connection`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Connection "multiprocessing.connection.Connection"); - подключенный и читаемый объект [`socket.socket`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/socket.html#socket.socket "socket.socket"); или - [`sentinel`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.sentinel "multiprocessing.Process.sentinel") атрибут объекта [`Process`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process "multiprocessing.Process"). Соединение или объект сокет готов, когда имеются данные, доступные для чтения из него, или другой конец закрыт. **Unix**: `wait(object_list, timeout)` почти эквивалентный `select.select(object_list, [], [], timeout)`. Разница в том, что, если [`select.select()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/select.html#select.select "select.select") прерывается сигналом, он может поднять [`OSError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#OSError "OSError") с числом ошибок `EINTR`, тогда как [`wait()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.wait "multiprocessing.connection.wait") не будет. **Windows**: Элемент в *object\_list* должен или быть целочисленным обработчиком, который ожидает (waitable) (согласно определению используемый документацией функции Win32 `WaitForMultipleObjects()`), или это может быть объект с методом `fileno()`, с каким возвращает ручка сокет или пайп обращаются. (Обратите внимание, что дескрипторы пайпа и сокет **не** являются дескрипторами ожидания. Добавлено в версии 3.3. **Примеры** Следующий код сервера создает слушателя, который использует `'secret password'` в качестве ключа идентификации. Затем он ожидает подключения и передает некоторые данные клиенту: ``` from multiprocessing.connection import Listener from array import array address = ('localhost', 6000) # семейство выведено как 'AF_INET' with Listener(address, authkey=b'secret password') as listener: with listener.accept() as conn: print('connection accepted from', listener.last_accepted) conn.send([2.25, None, 'junk', float]) conn.send_bytes(b'hello') conn.send_bytes(array('i', [42, 1729])) ``` Следующая код подключается к серверу и получает некоторые данные от сервера: ``` from multiprocessing.connection import Client from array import array address = ('localhost', 6000) with Client(address, authkey=b'secret password') as conn: print(conn.recv()) # => [2.25, None, 'junk', float] print(conn.recv_bytes()) # => 'hello' arr = array('i', [0, 0, 0, 0, 0]) print(conn.recv_bytes_into(arr)) # => 8 print(arr) # => array('i', [42, 1729, 0, 0, 0]) ``` Следующая код использует [`wait()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.wait "multiprocessing.connection.wait") для ожидания сообщений от нескольких процессов одновременно: ``` import time, random from multiprocessing import Process, Pipe, current_process from multiprocessing.connection import wait def foo(w): for i in range(10): w.send((i, current_process().name)) w.close() if __name__ == '__main__': readers = [] for i in range(4): r, w = Pipe(duplex=False) readers.append(r) p = Process(target=foo, args=(w,)) p.start() # Мы закрываем записываемый конец пайп, чтобы убедиться, что p является # единственным процессом, который владеет дескриптором для него. Это гарантирует, # что когда p закроет свой дескриптор для записываемого конца, wait() # быстро сообщит о читаемом конце как о прочитанном. w.close() while readers: for r in wait(readers): try: msg = r.recv() except EOFError: readers.remove(r) else: print(msg) ``` #### Форматы адреса[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-address-formats "Ссылка на этот заголовок") - Адрес `'AF_INET'` - кортеж формы `(hostname, port)`, где *hostname* - строка, а *port* - целое число. - Адрес `'AF_UNIX'` - это строка, представляющий имя файла в файловой системе. - Адрес `'AF_PIPE'` представляет собой строку вида `r'\\.\pipe{PipeName}'`. Чтобы использовать [`Client()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Client "multiprocessing.connection.Client") для подключения к именованному каналу на удаленном компьютере с именем *ServerName*, вместо этого следует использовать адрес формы `r'\ServerName\pipe{PipeName}'`. Обратите внимание, что любая строка, начинающаяся с двух обратных косых черт, по умолчанию принимается как `'AF_PIPE'` адрес, а не `'AF_UNIX'` адрес. ### Ключи аутентификации[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-auth-keys "Ссылка на этот заголовок") Когда каждый использует [`Connection.recv`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Connection.recv "multiprocessing.connection.Connection.recv"), полученными данными является автоматически unpickled. К сожалению, отмена извлечения данных из ненадежного источника является угрозой безопасности. Поэтому [`Listener`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Listener "multiprocessing.connection.Listener") и [`Client()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.connection.Client "multiprocessing.connection.Client") используйте модуль [`hmac`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/hmac.html#module-hmac "hmac: Реализация ключевого хеширования для аутентификации сообщений (HMAC)") для обеспечения дайджест-аутентификации. Ключ аутентификации - это байт строка, который можно рассматривать как пароль: после установления соединения оба конца потребуют подтверждения того, что другой знает ключ аутентификации. (Демонстрирующий то, что оба конца используют тот же ключ, делает **не**, включают отправку ключа по связи.) Если идентификацию запрошенный, но никакой ключ идентификации не определен тогда, возвращает значение `current_process().authkey` - используемый (см. [`Process`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process "multiprocessing.Process")). Этот значение будет автоматически унаследован любым объектом [`Process`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process "multiprocessing.Process"), что текущий процесс создает. Это означает, что (по умолчанию) все процессы многопроцессорной программы будут совместно использовать один ключ аутентификации, который может быть используемый при установке соединений между собой. Подходящие ключи аутентификации также могут быть сгенерированы с использованием [`os.urandom()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/os.html#os.urandom "os.urandom"). ### Логирование[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id22 "Ссылка на этот заголовок") Доступна некоторая поддержка логирование. Однако следует отметить, что пакет [`logging`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/logging.html#module-logging "logging: Гибкая система регистрации событий для приложений.") не использует общие блокировки процессов, что позволяет (в зависимости от типа обработчик) смешивать сообщения из различных процессов. `multiprocessing.``get_logger`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.get_logger "Ссылка на это определение") Возвращает логгер используемый по [`multiprocessing`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing "multiprocessing: Процессный параллелизм."). При необходимости будет создан новый. При первом создании логгер имеет уровень `logging.NOTSET` и не имеет обработчик по умолчанию. Сообщения, отправляемые этому логгер, по умолчанию не распространяются на корневой логгер. Обратите внимание, что в Windows дочерние процессы наследуют только уровень логгер родительского процесса - любая другая настройка логгер не наследуется. `multiprocessing.``log_to_stderr`()[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.log_to_stderr "Ссылка на это определение") Эта функция выполняет вызов [`get_logger()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.get_logger "multiprocessing.get_logger"), но в дополнение к возвращению логгер, созданного get\_logger, она добавляет обработчик, который отправляет вывод в [`sys.stderr`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/sys.html#sys.stderr "sys.stderr"), используя формат `'[%(levelname)s/%(processName)s] %(message)s'`. Ниже приведен пример сеанса с включенной функцией логирование: \>\>\> ``` >>> import multiprocessing, logging >>> logger = multiprocessing.log_to_stderr() >>> logger.setLevel(logging.INFO) >>> logger.warning('doomed') [WARNING/MainProcess] doomed >>> m = multiprocessing.Manager() [INFO/SyncManager-...] child process calling self.run() [INFO/SyncManager-...] created temp directory /.../pymp-... [INFO/SyncManager-...] manager serving at '/.../listener-...' >>> del m [INFO/MainProcess] sending shutdown message to manager [INFO/SyncManager-...] manager exiting with exitcode 0 ``` Полную таблицу уровней логирование см. в модуле [`logging`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/logging.html#module-logging "logging: Гибкая система регистрации событий для приложений."). ### Модуль [`multiprocessing.dummy`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing.dummy "multiprocessing.dummy: Обертка заглушка вокруг потоков.")[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing.dummy "Ссылка на этот заголовок") [`multiprocessing.dummy`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing.dummy "multiprocessing.dummy: Обертка заглушка вокруг потоков.") копирует API [`multiprocessing`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing "multiprocessing: Процессный параллелизм."), но является не более чем оболочкой для модуля [`threading`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html#module-threading "threading: Потоковый параллелизм."). В частности, функция `Pool`, предоставляемая [`multiprocessing.dummy`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing.dummy "multiprocessing.dummy: Обертка заглушка вокруг потоков."), возвращает экземпляр [`ThreadPool`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.ThreadPool "multiprocessing.pool.ThreadPool"), который является подклассом [`Pool`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool "multiprocessing.pool.Pool"), который поддерживает все те же вызовы методов, но использует пул рабочих потоков, а не рабочих процессов. *class* `multiprocessing.pool.``ThreadPool`(\[*processes*\[, *initializer*\[, *initargs*\]\]\])[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.ThreadPool "Ссылка на это определение") Объект пула потоков, который управляет пулом рабочих потоков, которым могут быть отправлены задания. Экземпляры [`ThreadPool`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.ThreadPool "multiprocessing.pool.ThreadPool") полностью совместимы по интерфейсу с экземплярами [`Pool`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool "multiprocessing.pool.Pool"), и их ресурсами также необходимо правильно управлять, используя пул в качестве диспетчера контекста или вызывая [`close()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.close "multiprocessing.pool.Pool.close") и [`terminate()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool.terminate "multiprocessing.pool.Pool.terminate") вручную. *processes* - количество используемых рабочих потоков. Если *processes* - `None`, то используется номер, возвращенный [`os.cpu_count()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/os.html#os.cpu_count "os.cpu_count"). Если *initializer* не `None`, то каждый рабочий процесс при запуске будет вызывать `initializer(*initargs)`. В отличие от [`Pool`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool "multiprocessing.pool.Pool"), *maxtasksperchild* и *context* не могут быть предоставлены. > Примечание > > [`ThreadPool`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.ThreadPool "multiprocessing.pool.ThreadPool") имеет тот же интерфейс, что и [`Pool`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool "multiprocessing.pool.Pool"), который разработан на основе пула процессов и предшествует введению модуля [`concurrent.futures`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/concurrent.futures.html#module-concurrent.futures "concurrent.futures: Конурентное выполнение вычислений с использованием потоков или процессов."). Таким образом, он наследует некоторые операции, которые не имеют смысла для пула, поддерживаемого потоками, и имеет свой собственный тип для представления состояния асинхронных заданий, [`AsyncResult`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.AsyncResult "multiprocessing.pool.AsyncResult"), который не понимается никакими другими библиотеками. > > Пользователям обычно следует использовать [`concurrent.futures.ThreadPoolExecutor`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/concurrent.futures.html#concurrent.futures.ThreadPoolExecutor "concurrent.futures.ThreadPoolExecutor"), который имеет более простой интерфейс, изначально спроектированный для потоков, и который возвращает экземпляры [`concurrent.futures.Future`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/concurrent.futures.html#concurrent.futures.Future "concurrent.futures.Future"), совместимые со многими другими библиотеками, включая [`asyncio`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/asyncio.html#module-asyncio "asyncio: Асинхронный I/O."). ## Программирование рекомендаций[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-programming "Ссылка на этот заголовок") Существуют определенные руководящие принципы и идиомы, которых следует придерживаться при использовании [`multiprocessing`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing "multiprocessing: Процессный параллелизм."). ### Все методы начала[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id24 "Ссылка на этот заголовок") Следующее относится ко всем методам запуска. Избегайте разделенного состояние > Насколько это возможно, следует стараться избегать переноса больших объемов данных между процессами. > > Вероятно, лучше всего использовать очереди или пайпы для обмена данными между процессами, чем использовать примитивы синхронизации более низкого уровня. Picklability > Убедитесь в том, что аргументы для методов прокси-серверов доступны. Безопасность потоков прокси > Не используйте прокси-объект из нескольких поток, если вы не защитите его с помощью блокировки. > > (Никогда нет проблемы с различными процессами, используя прокси *same*.) Присоединение к процессам зомби > В Unix, когда процесс заканчивается, но не был присоединен, он становится зомби. Никогда не должно быть очень многих, потому что каждый раз новый процесс начинается (или [`active_children()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.active_children "multiprocessing.active_children") называют), все законченные процессы, к которым еще не присоединились, будет присоединен. Кроме того, вызов [`Process.is_alive`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.is_alive "multiprocessing.Process.is_alive") завершенного процесса присоединится к процессу. Тем не менее, это, вероятно, хорошая практика, чтобы явно присоединиться ко всем процессам, которые вы начинаете. Лучше наследовать, чем pickle/unpickle > При использовании методов запуска *spawn* или *forkserver* многие типы из [`multiprocessing`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing "multiprocessing: Процессный параллелизм.") должны быть подбираемыми, чтобы их могли использовать дочерние процессы. Однако обычно следует избегать отправки общих объектов другим процессам с использованием пайпов или очередей. Вместо этого следует упорядочить программу так, чтобы процесс, которому необходим доступ к общему ресурсу, созданному в другом месте, мог наследовать его от предшествующего процесса. Постарайтесь не заканчивать процессы > Используя метод [`Process.terminate`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.terminate "multiprocessing.Process.terminate"), чтобы остановить процесс склонно заставить любые общие ресурсы (такие как замки, семафоры, пайпы и очереди) в настоящее время являющийся используемый процессом становиться сломанными или недоступными к другим процессам. > > Поэтому, вероятно, лучше только рассмотреть использование [`Process.terminate`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.terminate "multiprocessing.Process.terminate") на процессах, которые никогда не используют общих ресурсов. Объединение процессов, использующих очереди > Следует иметь в виду, что процесс, поставивший элементы в очередь, будет ждать завершения до тех пор, пока все буферизированные элементы не будут поданы «питателем» поток в нижележащий пайп. (Дочерний процесс может вызвать метод [`Queue.cancel_join_thread`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Queue.cancel_join_thread "multiprocessing.Queue.cancel_join_thread") очереди, чтобы избежать такого поведения. > > Это означает, что при каждом использовании очереди необходимо убедиться, что все элементы, помещенные в очередь, будут удалены до присоединения процесса. В противном случае вы не можете быть уверены, что процессы, поставившие элементы в очередь, завершатся. Также следует помнить, что недемонические процессы будут присоединяться автоматически. > > Примером взаимоблокировки является следующее: > ``` > from multiprocessing import Process, Queue def f(q): q.put('X' * 1000000) if __name__ == '__main__': queue = Queue() p = Process(target=f, args=(queue,)) p.start() p.join() # это мертвая блокировка obj = queue.get() > ``` > Фиксация здесь должна была бы обменять последние две линии (или просто удалить линию `p.join()`). Явная передача ресурсов дочерним процессам > На Unix, используя метод начала *fork*, дочерний процесс может использовать общий ресурс, созданный в родительском процессе, используя глобальный ресурс. Однако лучше передать объект в качестве аргумента конструктору для дочернего процесса. > > Кроме обеспечения совместимости код (потенциально) с Windows и другими методами запуска, это также гарантирует, что до тех пор, пока дочерний процесс еще жив, объект не будет мусором собран в родительском процессе. Это может быть важно, если какой-либо ресурс освобождается при сборе мусора объекта в родительском процессе. > > Таким образом для сущность: > ``` > from multiprocessing import Process, Lock def f(): ... сделать что-то используя "lock" ... if __name__ == '__main__': lock = Lock() for i in range(10): Process(target=f).start() > ``` > следует переписать как: > ``` > from multiprocessing import Process, Lock def f(l): ... сделать что-нибудь, используя "l" ... if __name__ == '__main__': lock = Lock() for i in range(10): Process(target=f, args=(lock,)).start() > ``` Остерегайтесь замены [`sys.stdin`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/sys.html#sys.stdin "sys.stdin") на «файл, как объект» > [`multiprocessing`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing "multiprocessing: Процессный параллелизм.") изначально безоговорочно вызвается: > ``` > os.close(sys.stdin.fileno()) > ``` > в методе `multiprocessing.Process._bootstrap()` — это привело к проблемам с процессами в процессах. Это было изменено на: > ``` > sys.stdin.close() sys.stdin = open(os.open(os.devnull, os.O_RDONLY), closefd=False) > ``` > Который решает основную проблему процессов, сталкивающихся друг с другом приводящим к плохой ошибке файла дескриптор, но вводит потенциальную опасность для заявлений, которые заменяют [`sys.stdin()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/sys.html#sys.stdin "sys.stdin") «подобным файлу объектом» с буферизующей продукцией. Эта опасность заключается в том, что если несколько процессов вызывают [`close()`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/io.html#io.IOBase.close "io.IOBase.close") на этом файловом объекте, это может привести к тому, что одни и те же данные будут очищены на объекте несколько раз, что приведет к повреждению. > > Если вы пишете подобный файлу объект и осуществляете ваш собственный кэширование, вы можете сделать его безопасным от вилки, храня pid каждый раз, когда вы прилагаете к кэш и отказу от кэш, когда pid изменяется. Например: > ``` > @property def cache(self): pid = os.getpid() if pid != self._pid: self._pid = pid self._cache = [] return self._cache > ``` > Дополнительные сведения см. в разделах [bpo-5155](https://bugs.python.org/issue5155), [bpo-5313](https://bugs.python.org/issue5313) и [bpo-5331](https://bugs.python.org/issue5331) ### Методы запуска *spawn* и *forkserver*[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#spawn-forkserver "Ссылка на этот заголовок") Есть некоторые дополнительное ограничение, которые не относятся к методу начала *fork*. Больше picklability > Убедитесь, что все аргументы для `Process.__init__()` доступны. Кроме того, если вы, подкласс [`Process`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process "multiprocessing.Process") тогда удостоверяется, что сущности будет picklable, когда метод [`Process.start`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.start "multiprocessing.Process.start") назовут. Глобальные переменные > Принять во внимание, что, если пробег код в дочернем процессе пытается получить доступ к глобальной переменной, то значение он видит (если таковые имеются) может не совпасть с значение в родительском процессе в то время, когда вызван [`Process.start`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.Process.start "multiprocessing.Process.start"). > > Однако глобальные переменные, являющиеся только константами уровня модуля, не вызывают проблем. Безопасный импорт основного модуля > Удостоверьтесь, что главный модуль может быть безопасно импортирован новым Python интерпретатор, не вызывая непреднамеренные побочные эффекты (такой старт нового процесса). > > Например, использование метода начала *spawn* или *forkserver*, управляющего следующим модулем, потерпело бы неудачу с [`RuntimeError`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/exceptions.html#RuntimeError "RuntimeError"): > ``` > from multiprocessing import Process def foo(): print('hello') p = Process(target=foo) p.start() > ``` > Вместо этого следует защитить «точку входа» программы, используя `if __name__ == '__main__':` следующим образом: > ``` > from multiprocessing import Process, freeze_support, set_start_method def foo(): print('hello') if __name__ == '__main__': freeze_support() set_start_method('spawn') p = Process(target=foo) p.start() > ``` > (Строка `freeze_support()` может быть опущена, если программа будет запущена нормально, а не заморожена. > > Это позволяет недавно порожденному Python интерпретатор безопасно импортировать модуль и затем управлять функцией `foo()` модуля. > > Аналогичные ограничения применяются в случае создания пула или менеджера в главном модуле. ## Примеры[¶](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-examples "Ссылка на этот заголовок") Демонстрация создания и использования настраиваемых менеджеров и прокси: ``` from multiprocessing import freeze_support from multiprocessing.managers import BaseManager, BaseProxy import operator ## class Foo: def f(self): print('you called Foo.f()') def g(self): print('you called Foo.g()') def _h(self): print('you called Foo._h()') # A simple generator function def baz(): for i in range(10): yield i*i # Proxy type for generator objects class GeneratorProxy(BaseProxy): _exposed_ = ['__next__'] def __iter__(self): return self def __next__(self): return self._callmethod('__next__') # Function to return the operator module def get_operator_module(): return operator ## class MyManager(BaseManager): pass # register the Foo class; make `f()` and `g()` accessible via proxy MyManager.register('Foo1', Foo) # register the Foo class; make `g()` and `_h()` accessible via proxy MyManager.register('Foo2', Foo, exposed=('g', '_h')) # register the generator function baz; use `GeneratorProxy` to make proxies MyManager.register('baz', baz, proxytype=GeneratorProxy) # register get_operator_module(); make public functions accessible via proxy MyManager.register('operator', get_operator_module) ## def test(): manager = MyManager() manager.start() print('-' * 20) f1 = manager.Foo1() f1.f() f1.g() assert not hasattr(f1, '_h') assert sorted(f1._exposed_) == sorted(['f', 'g']) print('-' * 20) f2 = manager.Foo2() f2.g() f2._h() assert not hasattr(f2, 'f') assert sorted(f2._exposed_) == sorted(['g', '_h']) print('-' * 20) it = manager.baz() for i in it: print('<%d>' % i, end=' ') print() print('-' * 20) op = manager.operator() print('op.add(23, 45) =', op.add(23, 45)) print('op.pow(2, 94) =', op.pow(2, 94)) print('op._exposed_ =', op._exposed_) ## if __name__ == '__main__': freeze_support() test() ``` Использование [`Pool`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing.pool.Pool "multiprocessing.pool.Pool"): ``` import multiprocessing import time import random import sys # # Functions used by test code # def calculate(func, args): result = func(*args) return '%s says that %s%s = %s' % ( multiprocessing.current_process().name, func.__name__, args, result ) def calculatestar(args): return calculate(*args) def mul(a, b): time.sleep(0.5 * random.random()) return a * b def plus(a, b): time.sleep(0.5 * random.random()) return a + b def f(x): return 1.0 / (x - 5.0) def pow3(x): return x ** 3 def noop(x): pass # # Test code # def test(): PROCESSES = 4 print('Creating pool with %d processes\n' % PROCESSES) with multiprocessing.Pool(PROCESSES) as pool: # # Tests # TASKS = [(mul, (i, 7)) for i in range(10)] + \ [(plus, (i, 8)) for i in range(10)] results = [pool.apply_async(calculate, t) for t in TASKS] imap_it = pool.imap(calculatestar, TASKS) imap_unordered_it = pool.imap_unordered(calculatestar, TASKS) print('Ordered results using pool.apply_async():') for r in results: print('\t', r.get()) print() print('Ordered results using pool.imap():') for x in imap_it: print('\t', x) print() print('Unordered results using pool.imap_unordered():') for x in imap_unordered_it: print('\t', x) print() print('Ordered results using pool.map() --- will block till complete:') for x in pool.map(calculatestar, TASKS): print('\t', x) print() # # Test error handling # print('Testing error handling:') try: print(pool.apply(f, (5,))) except ZeroDivisionError: print('\tGot ZeroDivisionError as expected from pool.apply()') else: raise AssertionError('expected ZeroDivisionError') try: print(pool.map(f, list(range(10)))) except ZeroDivisionError: print('\tGot ZeroDivisionError as expected from pool.map()') else: raise AssertionError('expected ZeroDivisionError') try: print(list(pool.imap(f, list(range(10))))) except ZeroDivisionError: print('\tGot ZeroDivisionError as expected from list(pool.imap())') else: raise AssertionError('expected ZeroDivisionError') it = pool.imap(f, list(range(10))) for i in range(10): try: x = next(it) except ZeroDivisionError: if i == 5: pass except StopIteration: break else: if i == 5: raise AssertionError('expected ZeroDivisionError') assert i == 9 print('\tGot ZeroDivisionError as expected from IMapIterator.next()') print() # # Testing timeouts # print('Testing ApplyResult.get() with timeout:', end=' ') res = pool.apply_async(calculate, TASKS[0]) while 1: sys.stdout.flush() try: sys.stdout.write('\n\t%s' % res.get(0.02)) break except multiprocessing.TimeoutError: sys.stdout.write('.') print() print() print('Testing IMapIterator.next() with timeout:', end=' ') it = pool.imap(calculatestar, TASKS) while 1: sys.stdout.flush() try: sys.stdout.write('\n\t%s' % it.next(0.02)) except StopIteration: break except multiprocessing.TimeoutError: sys.stdout.write('.') print() print() if __name__ == '__main__': multiprocessing.freeze_support() test() ``` Пример использования очередей для подачи задач в коллекцию рабочих процессов и сбора результатов: ### [Содержание](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/contents.html) - [`multiprocessing` — Процессный параллелизм](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html) - [Введение](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id1) - [Класс `Process`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#process) - [Контексты и методы запуска](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id2) - [Обмен объектами между процессами](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id3) - [Синхронизация между процессами](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id4) - [Совместное использование состояние между процессами](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id5) - [Использование пула воркеров](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id6) - [Ссылка](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id7) - [`Process` и исключения](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id8) - [Пайпы и очереди](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id9) - [Разное](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id10) - [Объекты связи](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id11) - [Примитивы синхронизации](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id12) - [Разделенные объекты `ctypes`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#ctypes) - [Модуль `multiprocessing.sharedctypes`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing.sharedctypes) - [Менеджеры](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-managers) - [Настраиваемые менеджеры](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id14) - [Использование удаленного менеджера](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id15) - [Прокси объекты](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-proxy-objects) - [Очистка](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id17) - [Процессные пулы](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing.pool) - [Слушатели и клиенты](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing.connection) - [Форматы адреса](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-address-formats) - [Ключи аутентификации](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-auth-keys) - [Логирование](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id22) - [Модуль `multiprocessing.dummy`](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#module-multiprocessing.dummy) - [Программирование рекомендаций](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-programming) - [Все методы начала](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#id24) - [Методы запуска *spawn* и *forkserver*](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#spawn-forkserver) - [Примеры](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html#multiprocessing-examples) #### Предыдущий раздел [`threading` — Потоковый параллелизм](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html "предыдущая глава") #### Следующий раздел [`multiprocessing.shared_memory` — Предоставляет общую память для прямого доступа между процессами](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.shared_memory.html "следующая глава") ### Эта страница - [Сообщить об ошибке](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/bugs.html) « ### Навигация - [указатель](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/genindex.html "Алфавитный указатель") - [модули](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/py-modindex.html "Содержание модулей Python") \| - [вперёд](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.shared_memory.html "multiprocessing.shared_memory — Предоставляет общую память для прямого доступа между процессами") \| - [назад](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/threading.html "threading — Потоковый параллелизм") \| - ![](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/_static/py.png) - [Python](https://digitology.tech/) » - [3\.8.8 Документация](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/index.html) » - [Стандартная библиотека Python](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/index.html) » - [Конкурентное выполнение](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/library/concurrency.html) » - \| [Поддержать первод](http://grep.cs.msu.ru/python3.8_RU/digitology.tech/docs/python_3/donate.html) ![](https://mc.yandex.ru/watch/65351827) ©Авторские права Digitology.tech. Обновлено: апр. 06, 2021.
Readable Markdownnull
Shard151 (laksa)
Root Hash13936146405119744351
Unparsed URLru,msu!cs,grep,/python3.8_RU/digitology.tech/docs/python_3/library/multiprocessing.html h80