Не работает многопроцессорный семафор Python - PullRequest
0 голосов
/ 16 мая 2018

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

Как мне заставить его уважать семафор?

Вот упрощенная версия моего кодау него та же проблема при запуске (я работаю в Windows с Python 2.7.11 (это нельзя изменить)):

import multiprocessing

rightofway = multiprocessing.Semaphore(1)

def writenum(number):
    rightofway.acquire()
    print("[+] - " + str(number))
    rightofway.release()
    return

def main():
    starting = 0
    ending = 50

    list = range(starting, ending)

    pool = multiprocessing.Pool(10)
    pool.map(writenum, list)
    return

#Required for Windows multiprocessing
if __name__ == '__main__':
    main()

Вот пример искаженного вывода:

[+] - 0
[+] - 1
[+] - 2
[+] - 3
[+] - 4
[+] - 5
[+] - 6
[+] - 7
[[+] - 8
+] - 10[
+] - 9[+] - 11
[+] - 12

[[+] - 13+] - 14

[[+] - 15+] - 16

[[+] - 18+] - 17

[[+] - 19+] - 20

[[+] - 22+] - 21

[[+] - 23+] - 24

[[+] - 26+] - 25

[[+] - 27+] - 28

[[+] - 30+] - 29

[[+] - 31+] - 32

[[+] - 34+] - 33

[[+] - 35+] - 36

[[+] - 38+] - 37

[[+] - 39+] - 40

[[+] - 42+] - 41

[[+] - 43+] - 44

[[+] - 46+] - 45

[[+] - 47+] - 48

[+] - 49

Вот пример вывода, который я хочу (заметьте, я не забочусь о порядке):

[+] - 0
[+] - 1
[+] - 2
[+] - 3
[+] - 4
[+] - 5
[+] - 6
[+] - 7
[+] - 8
[+] - 9
[+] - 10
[+] - 11
[+] - 12
[+] - 13
[+] - 14
[+] - 15
[+] - 16
[+] - 17
[+] - 18
[+] - 19
[+] - 20
[+] - 21
[+] - 22
[+] - 23
[+] - 24
[+] - 25
[+] - 26
[+] - 27
[+] - 28
[+] - 29
[+] - 30
[+] - 31
[+] - 32
[+] - 33
[+] - 36
[+] - 34
[+] - 35
[+] - 37
[+] - 38
[+] - 40
[+] - 39
[+] - 41
[+] - 42
[+] - 44
[+] - 43
[+] - 45
[+] - 46
[+] - 48
[+] - 47
[+] - 49

Ответы [ 2 ]

0 голосов
/ 17 мая 2018

Чтобы все было немного проще, подписка сработала для меня.Проверено на Win10. TL; DR - использовать замки не семафорные

import multiprocessing

rightofway = multiprocessing.Lock()

def writenum(number):

    with rightofway:
        print("[+] - " + str(number))

    return

def main():
    starting = 0
    ending = 50

    list = range(starting, ending)

    pool = multiprocessing.Pool(10)
    pool.map(writenum, list)
    return

#Required for Windows multiprocessing
if __name__ == '__main__':
    main()
0 голосов
/ 17 мая 2018

Ваш вопрос похож на этот .

Из руководства по многопроцессорному программированию.

Явно передает ресурсы дочерним процессам

... лучше передать объект в качестве аргумента конструктору для дочернего процесса.

Помимо обеспечения совместимости кода (потенциально) с Windows ...

В Windows вам необходимо передать общие объекты в список аргументов конструктора процесса.В противном случае дочерний процесс получит совершенно новую копию вместо родительской.Вот почему у вас создается впечатление, что Semaphore не работает.Два процесса создают свой собственный отдельный объект Semaphore вместо совместного использования одного и того же.

Чтобы передать объект Semaphore в Pool в Windows, вам нужно немного потрудиться, но не слишком.Поскольку вы не можете напрямую передать объект Semaphore в функцию writenum, вам нужно полагаться на Pool initializer.

from multiprocessing import Semaphore, Pool

mutex = None

def initializer(semaphore):
    """This function is run at the Pool startup. 
    Use it to set your Semaphore object in the child process.

    """
    global mutex

    mutex = semaphore

def writenum(args):
    with mutex:
        print "[+] - " + str(number)

def main():
    semaphore = Semaphore()
    pool = Pool(initializer=initializer, initargs=[semaphore])

    numbers = range(50)

    pool.map(writenum, numbers)

EDIT: только что заметил, что вместо этого написал о LockSemaphore.Основные рассуждения остаются прежними.

...