Подпроцесс Python3 в многопроцессорности

Я новичок в написании параллельного кода.

Я пишу код, который берет идентификатор пользователя и пытается вернуть полное имя пользователя, запрос занимает секунду или около того, поэтому я надеялся задействовать многопроцессорность для более быстрого сбора данных; Я думаю, что близок, но я не понимаю, как правильно реализовать фреймворк.

from subprocess import getoutput
from multiprocessing import Pool

all_users = ['User1', 'User2', 'User3', 'User4', 'User5', 'User6'] # example list

def get_name(userid):
    name = getoutput('net users {} /domain | findstr "full name:"'.format(userid)).replace('Full Name', '').strip().split('\n')[0]
    return {userid : name}


if __name__ == '__main__':
    with Pool(4) as p:
        print(p.map(get_name, all_users))

    print(' --------- finished')

print(' - exiting - '))

Это всего лишь один шаг в многоэтапном сценарии; и вывод выглядит следующим образом: (игнорируйте часть «имя пользователя не может быть найдено», просто пример)

 - exiting -
 - exiting -
 - exiting -
 - exiting -
[{'User1': 'The user name could not be found.'}, {'User2': 'The user name could not be found.'}, {'User3': 'The user name could not be found.'}, {'User4': 'The user name could not be found.'}, {'User5': 'The user name could not be found.'}, {'User6': 'The user name could not be found.'}]
 --------- finished
 - exiting -

Я пытаюсь структурировать программу следующим образом:

  1. Получить список пользователей
  2. Преобразование идентификатора в имена (как можно скорее, создавая отдельный процесс для каждого вызова функции)
  3. Дождитесь полного завершения 2-го шага, а затем работайте с возвращенными данными;

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

Нашел интересное объяснение; stackoverflow.com/a/14626474/9039988

h3xus 09.01.2019 15:05
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
1
756
3

Ответы 3

Вам нужно использовать оператор pool.close () в вашем цикле with:

with Pool(4) as p:
    print(p.map(get_name, all_users))
    p.close()

Разве оператор with не должен автоматически обрабатывать закрытие объекта Pool?

h3xus 09.01.2019 14:54

Джош Хейс уже дал правильный ответ. Если вы используете такой пул, он будет вызывать terminate при выходе (https://docs.python.org/3.4/library/multiprocessing.html?highlight=process), начиная с Python 3.3. Вы должны добавить p.close(), чтобы правильно закончить. Однако ваша последняя скобка слишком велика, и вы не должны видеть более одной печати finished и exiting, потому что эти вызовы не входят в пул. Как начать свой сценарий? Какую версию Python вы используете?

Редактировать: Вы можете попробовать добавить:

import os

def info(title):
    print(title)
    print('module name:', __name__)
    print('parent process:', os.getppid())
    print('process id:', os.getpid())

all_users = ['User1', 'User2', 'User3', 'User4', 'User5', 'User6'] # example list

def get_name(userid):
    name = getoutput('net users {} /domain | findstr "full name:"'.format(userid)).replace('Full Name', '').strip().split('\n')[0]
    print(info("p "))
    return {userid : name}

и вызовите info("whatever") вместо exiting и посмотрите, какие процессы здесь работают. Какую ОС вы используете? По крайней мере, в Linux это имеет смысл.

Я использую Python 3.6.3 x64; Это действительно весь сценарий, который я вставил, и результат выглядит странным ... 4 оператора выхода в начале, затем сценарий запускается, а затем все остальное происходит по порядку; P.S. Оператор with не обрабатывает автоматическое закрытие объектов Pool?

h3xus 09.01.2019 14:57

Я немного смущен. Я тестировал его с помощью Python 3.5.2, и мои процессы не завершаются, а основной процесс ожидает завершения всех. Однако в документации указано, что terminate() Stops the worker processes immediately without completing outstanding work. When the pool object is garbage collected terminate() will be called immediately. Новое в версии 3.3: Объекты пула теперь поддерживают протокол управления контекстом - см. Типы диспетчера контекста. __enter __ () возвращает объект пула, а __exit __ () вызывает terminate ().

M. Hieronymus 09.01.2019 15:22

Ответ на аналогичный вопрос был дан по следующей ссылке: множественный вывод, возвращаемый функцией многопроцессорной обработки Python

Обобщить:

# Import stuff
#If the worker code is in the main thread, exclude it from the if statement:
def worker():
    #worker code
if __name__ == '__main__':
    #execute whatever you want, it will only be executed 
    #as often as you intend it to
    #execute the function that starts multiprocessing, 

#All code outside of the if statement will be executed multiple times
#depending on the # of assigned worker threads.

Другие вопросы по теме