当新创建的路径通过时,池映射陷入无限循环

问题描述 投票:0回答:1

我想从基本文件夹创建多个文件夹,然后并行运行这些多个文件夹。当文件夹已经创建时它工作正常。然而,当我创建这些文件夹然后在单个 python 代码中运行多重处理时,它陷入无限循环。

工作代码(当adress_a和address_b已经存在时:

import os
from multiprocessing import Pool

Base_address='C:\\Users\\bappi\\Desktop\\Base_address'
address_a='C:\\Users\\bappi\\Desktop\\address_a'
address_b='C:\\Users\\bappi\\Desktop\\address_b'


Folders=['']*2

Folders[0]=address_a
Folders[1]=address_b


def call_exe(address):
    os.chdir(address)
    exe_file='Test.exe'
    os.system(exe_file)

if __name__ == '__main__':
    with Pool(2) as p:
        p.map(call_exe,Folders)

但是,当address_a和address_b不存在并且我想从基本文件夹创建它时,以下代码不起作用。

不工作代码:当我从基本文件夹创建 adrress_a 和 address_b 的副本时

import os
from multiprocessing import Pool
import shutil

Base_address='C:\\Users\\bappi\\Desktop\\Base_address'
address_a='C:\\Users\\bappi\\Desktop\\address_a'
address_b='C:\\Users\\bappi\\Desktop\\address_b'

shutil.copytree(Base_address, address_a)     # successfully folder created
shutil.copytree(Base_address, address_b)     # successfully folder created

Folders=['']*2

Folders[0]=address_a
Folders[1]=address_b


def call_exe(address):
    os.chdir(address)
    exe_file='Test.exe'
    os.system(exe_file)

if __name__ == '__main__':
    with Pool(2) as p:
        p.map(call_exe,Folders)   # This one stuck in infinite loop

python multiprocessing pool shutil
1个回答
0
投票

如果将光标悬停在标签上

multiprocessing
,您将看到:

当使用标签

multiprocessing
发布问题时,务必指定您正在执行的平台,因为它可以使您的代码正常运行与否产生巨大差异。

由于您没有指定平台,我可能会错误地假设它是使用 spawn 方法而不是 fork 方法来创建新进程的平台。即使情况并非如此,您也可能会在这个答案中发现一些对未来的价值。

当使用 spawn 方法创建进程并且您正在使用多处理(在本例中为多处理池)时,子进程将被创建并最初具有未初始化的内存。然后,对于每个子进程,Python 解释器都会被加载并在原始源程序中读取并执行。因此,在调用工作函数

call_exe
之前,将执行全局范围内的每个语句(导入语句、函数定义等)以初始化内存。

因此,如果您要创建一个包含 N 个进程的池,则全局范围内的语句将被执行 N 次,每个进程一次。其中一些语句可能不需要工作函数所需的正确初始化,例如工作函数未使用的模块/包的导入语句,但如果执行它可能不会造成不当损害。但其他不必要的全局语句可能会造成无法弥补的损害或降低效率,因为它们浪费了 CPU 和/或内存资源。因此,如果您在全局范围内有任何不想执行的内容,则必须将此类语句包含在检查

if __name__ == '__main__':
中,这只会对初始主进程评估为 True。 您在全球范围内拥有以下声明(除其他外):

shutil.copytree(Base_address, address_a)     # successfully folder created
shutil.copytree(Base_address, address_b)     # successfully folder created

对于多处理池中的每个进程,每条语句都会执行一次,总共执行 2 次,因为您的池大小为 2。第二个池进程的初始化必然会创建一个异常,因为目录将具有已经存在了。如果您运行的是 Python 3.8 或更高版本,您可以指定 dir_exists_ok=True 参数以允许目录已存在。但即便如此,当第一个池进程正在处理工作函数

call_exe
中的目录时,第二个池进程可能会通过调用
copytree
来修改目录。这些是在全球范围内造成不可挽回的伤害的言论。

在下面的代码中,我已将

call_exe
不需要的所有语句移至
if __name__ == '__main__':
块(其中一些语句,例如文件夹的导入语句或定义可能已留在名称检查之外,如下所示)在您的原始代码中,除了在初始化池进程时浪费一些 CPU 周期之外不会造成任何损害。

我还尝试遵循PEP 8 – Python代码风格指南来命名变量、间距等。我还发现您使用“地址”一词来引用文件夹/目录名称有点有点不寻常(

path
directory
directory_name
folder
folder_name
对于阅读代码的人来说都更有意义)。

import os

def call_exe(folder):
    os.chdir(folder)
    exe_file = 'Test.exe'
    os.system(exe_file)


if __name__ == '__main__':
    from multiprocessing import Pool
    import shutil

    # A Much simpler way to initialize the folders list
    # and to initialize the directories:

    base_folder = 'C:\\Users\\bappi\\Desktop\\Base_address'

    folders = [
        'C:\\Users\\bappi\\Desktop\\address_a',
        'C:\\Users\\bappi\\Desktop\\address_b'
    ]

    for folder in folders:
        shutil.copytree(base_folder, folder, dirs_exist_ok=True)  # successfully folder created

    with Pool(2) as p:
        p.map(call_exe, folders)
© www.soinside.com 2019 - 2024. All rights reserved.