Python 多处理信号量不工作
Python Multiprocessing Semaphore not working
我希望我的程序一次打印一行,但是它一次打印多行并造成乱码。我似乎无法找出为什么信号量没有阻止多个进程相互打印。
如何让它遵守信号量?
这是我的代码的简化版本,它在 运行 时有同样的问题(我 运行 在 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
您的问题类似于。
来自多处理编程指南。
Explicitly pass resources to child processes
... it is better to pass the object as an argument to the constructor for the child process.
Apart from making the code (potentially) compatible with Windows ...
在 Windows,您需要将共享对象传递给 Process 构造函数参数列表。否则,子进程将获得一个全新的副本,而不是父进程的副本。这就是为什么您会觉得 Semaphore
不起作用。这两个进程正在创建自己不同的 Semaphore
对象,而不是共享同一个对象。
要将 Semaphore
对象传递给 Windows 上的 Pool
,您需要费点功夫,但不要太多。由于您不能将 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)
编辑:刚注意到我写的是 Lock
而不是 Semaphore
。核心推理保持不变。
为了让事情变得更简单,Following 对我有用。在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()
我希望我的程序一次打印一行,但是它一次打印多行并造成乱码。我似乎无法找出为什么信号量没有阻止多个进程相互打印。
如何让它遵守信号量?
这是我的代码的简化版本,它在 运行 时有同样的问题(我 运行 在 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
您的问题类似于
来自多处理编程指南。
Explicitly pass resources to child processes
... it is better to pass the object as an argument to the constructor for the child process.
Apart from making the code (potentially) compatible with Windows ...
在 Windows,您需要将共享对象传递给 Process 构造函数参数列表。否则,子进程将获得一个全新的副本,而不是父进程的副本。这就是为什么您会觉得 Semaphore
不起作用。这两个进程正在创建自己不同的 Semaphore
对象,而不是共享同一个对象。
要将 Semaphore
对象传递给 Windows 上的 Pool
,您需要费点功夫,但不要太多。由于您不能将 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)
编辑:刚注意到我写的是 Lock
而不是 Semaphore
。核心推理保持不变。
为了让事情变得更简单,Following 对我有用。在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()