在 unix 下,在 python 中省略 "if __name__ == '__main__'" 多处理语句是否安全?

is it safe to leave out "if __name__ == '__main__'" statement for multiprocessing in python under unix?

我正在尝试在 python 中实现一个灵活的管道,我已将其分成几个模块。 这些模块中的每一个都可以用作独立工具,但有时它们也可能必须相互导入功能。 我已将这些模块中的多个经常使用的一般简单函数放入一个“misc”模块中,该模块在需要时由所有其他模块导入。

现在,这些模块中的每一个都可能希望 运行 使用多处理(通常调用一些外部工具)并行执行某些功能。 所以我创建了一个通用的“run_parallel”函数,它将函数列表和相应的参数作为参数,确定每个函数的优先级并相应地在它们之上分配可用的核心,然后 运行s 这些函数并行使用 multiprocessing 和 starmap()。

现在我认为这个函数可以很好地放在“misc”模块中,并且可以在任何其他函数需要并行 运行 作业时导入。但是,如果我遵循(显然)一般规则 always 为此使用 if __name__ == '__main__ 语句,这意味着我无法导入此函数并在多个模块中重用它。我从来没有完全理解这个要求,但它似乎确实与 windows 有关,具体是什么?我的管道只能在 unix 下工作。

这是否意味着我必须为我的每个模块分别实现这个“run_parallel”方法? 或者,如果我的代码仅适用于 linux/unix 环境下的 运行,我可以安全地离开它吗?

编辑:我现在意识到我完全误解了多处理教程和用法示例中此语句的用法。我想,出于某种原因,在任何使用多处理中的东西的函数中也需要它(并且一直对为什么会这样感到困惑)。但是在这些例子中,他们也只保护了将调用该函数的示例代码部分,防止它在每次导入时自动被调用(正如我所想的那样,根本不阻止函数被导入)。完全是误会!

当您 运行 脚本或导入模块时,python 会执行在模块级别编写的所有代码。在像

这样的函数的情况下
def foo():
    pass

“执行”只是指将新编译的函数对象赋值给一个名为“foo”的变量。这些东西不需要用 if __name__ == "__main__": 块来保护。您只需要关心执行某个操作的代码,例如 调用 foo().

的代码

用于启动 python 程序的顶级脚本称为 "__main__"。您导入的模块不称为 "__main__" 并且 if __name__ == "__main__": 块毫无意义。重要的是模块是导入安全的。也就是说,导入模块应该总是安全的,除了初始化之外不做任何事情。模块的操作应始终在函数内部或从其他地方调用的 类。

顶层脚本不同,它实际上是 运行 程序。 if __name__ == "__main__": 用于使顶级脚本导入安全。对于像 Unix 这样的分叉系统,这无关紧要(至少对于多处理而言)。但是 Windows 需要生成一个新进程并导入顶层脚本 - 并且导入需要安全,它不能重新执行程序本身。

虽然您在 Unix 上不需要这种保护,但模块应该始终是导入安全的。对于顶级脚本来说,这也是一个很好的纪律。为什么在不需要时限制代码执行?

一个不错的脚本秘诀是

def main()
    do all the things
    return 0

if __name__ == "__main__":
    retcode = main()
    exit(retcode)