我在使用
pyvips
库处理图像的 Python 程序中遇到了一个奇怪的问题。这是我的问题的简化版本。
我尝试多次创建一个 numpy 数组(在我的简单示例中来自零)(在示例中为 2 次)。
当我按顺序执行时,一切都很好。当我使用
multiprocessing
模块时,它也能正常工作。但在我的测试过程中,我注意到当我依次快速执行这两个运行时,程序会冻结。因此就有了下面的程序。当我运行它时,它在多处理部分的第一个“步骤 3”之前冻结。
我认为它与垃圾收集机制有关,但我在这里迷失了。
我正在使用 python 3.11.3 和 pyvips 2.2.2(带有 vips-8.15.1)。我在 Linux 机器(基于 Ubuntu 22.04 的发行版)上使用 Spyder 及其 IPython 控制台。
import multiprocessing
import numpy as np
import pyvips
def myfunction(useless):
print("step 1")
image = pyvips.Image.new_from_array(np.zeros((8, 8, 3)), interpretation="rgb")
print("step 2")
res = np.asarray(image)
print("step 3")
return res
def main(nbpool):
srcrange = range(2)
if nbpool == 0:
res = list()
for srcid in srcrange:
res.append(myfunction(srcid))
return res
else:
pool = multiprocessing.Pool(nbpool)
return pool.map(myfunction, srcrange)
if __name__ == "__main__":
res1 = main(0)
print("Now with multiprocessing")
res2 = main(1)
您遇到的问题可能是由于多处理模块无法与 IPython 或 Jupyter 笔记本兼容。这是因为这些环境不是分叉安全的,并且多处理依赖于安全分叉 Python 解释器的能力。
潜在解决此问题的一种方法是在脚本开头使用 multiprocessing.set_start_method('spawn') 。这将使多处理模块为每个子进程创建一个新的 Python 解释器,这可以避免在非分叉安全的环境中分叉的问题。
以下是修改脚本的方法:
import multiprocessing
import numpy as np
import pyvips
# Set the start method for multiprocessing
multiprocessing.set_start_method('spawn')
def myfunction(useless):
print("step 1")
image = pyvips.Image.new_from_array(np.zeros((8, 8, 3)), interpretation="rgb")
print("step 2")
res = np.asarray(image)
print("step 3")
return res
def main(nbpool):
srcrange = range(2)
if nbpool == 0:
res = list()
for srcid in srcrange:
res.append(myfunction(srcid))
return res
else:
pool = multiprocessing.Pool(nbpool)
return pool.map(myfunction, srcrange)
if __name__ == "__main__":
res1 = main(0)
print("Now with multiprocessing")
res2 = main(1)
请注意,使用“spawn”启动方法可能会导致程序运行速度变慢,因为必须为每个子进程创建一个新的Python解释器。但是,它可以帮助避免在 IPython 或 Jupyter 笔记本等环境中分叉的问题。