Python 多处理循环 Python 文件而不是启动进程
Python Multiprocessing Looping Python File Instead of Starting Process
我正在尝试开始使用多处理,并且 运行 遇到了一些有趣的问题。我正在使用的代码如下(作为记录,此示例直接来自多处理文档):
from multiprocessing import Process
def f(name):
print('hello', name)
if __name__ == '__main__':
p = Process(target=f, args=('bob'))
p.start()
p.join()
这工作正常,并按应有的方式打印“hello bob”。但是,当我在 if 语句之前或之后向文件添加任何其他代码时,p 不会计算,并且我的文件循环回到开头并无休止地重新运行。例如,下面的代码给我这个问题:
from multiprocessing import Process
def f(name):
print('hello', name)
if __name__ == '__main__':
p = Process(target=f, args=('bob'))
p.start()
p.join()
test_input = input("test input")
我 运行 Python 使用 Windows 10、Pycharm v. 2021.3.2 和 Python 3.10.0。这是你们以前见过的问题吗?在这一点上,我开始怀疑它是否甚至是 Windows 和 Pycharm 或 Windows 和 Python 之间的问题,或者可能只是我缺乏经验的情况.
谢谢!
那个if __name__ == '__main__':
后卫很重要。在不使用 fork
的系统上,它通过在每个工作进程 中导入主脚本来模拟一个 fork
而没有 将其命名为 __main__
(它是名为 __mp_main__
IIRC)。任何在“主”脚本中只应 运行 的代码都需要受到该守卫的保护(它可以通过定义一个函数并在受保护的段内调用它来间接保护;该函数将在工作人员中定义,但不是 运行).
因此,要解决此问题,您需要做的就是缩进 test_input = input("test input")
,以便它受到 if __name__ == '__main__':
守卫的保护。在实际代码中,我尽量保持受保护的部分干净(这样我就不会意外地编写依赖全局状态的函数,当它不是 运行 作为主脚本时不存在,并且为了温和的性能优势在全局变量上使用函数局部变量),所以我会这样写:
from multiprocessing import Process
def f(name):
print('hello', name)
def main():
p = Process(target=f, args=('bob',))
p.start()
p.join()
test_input = input("test input")
if __name__ == '__main__':
main()
但这并不是绝对必要的。
关于ShadowRanger的回答,我觉得你也应该在'bob'后面加上逗号。
根据https://docs.python.org/3/library/multiprocessing.html
P如果要另外声明的话应该是这样的
p = Process(target=f, args=('bob',))
我想我会详细说明 ShadowRanger 的回答:
在 Windows 系统上,新的子流程是通过以下步骤创建的:
- 创建了一个新进程,其中 Python 解释器是 re-launched。
- Python 解释器 re-interprets 当前源程序执行 全局范围内的所有内容 以编译函数定义、初始化全局变量等.
- 最后,您的辅助函数
f
在这种情况下被调用,内存因此被初始化。
将创建子进程的代码放在由 if __name__ == '__main__':
控制的块中的原因是,如果您不这样做,那么由于上面的第 2 步,您将进入递归的无限循环创建新的子流程 ad inifinitum。 重点是只有在main函数中,变量__name__
才会有值'__main__';对于创建的任何子流程,它将具有不同的值。 因此创建新子流程的代码,即 p = Process(target=f, args=('bob',))
,将不会作为子流程初始化的一部分执行。
您的问题是由于语句 test_input = input("test input")
在全局范围内 而 不在 if __name__ == '__main__':
块内,因此它将作为子进程的初始化。因此,您的工作函数 f
不会 运行 直到满足此输入提示,然后当它 returns 您的主进程将再次发出提示。无论如何,这是我在 Windows 命令提示符下 运行 时看到的。也许 PyCharm 限制了从主线程以外的任何线程执行 input 语句。但是,即使在创建子流程时从该语句中抛出异常,我仍然不太明白您的程序将如何连续循环。不幸的是,我没有安装 PyCharm。
我正在尝试开始使用多处理,并且 运行 遇到了一些有趣的问题。我正在使用的代码如下(作为记录,此示例直接来自多处理文档):
from multiprocessing import Process
def f(name):
print('hello', name)
if __name__ == '__main__':
p = Process(target=f, args=('bob'))
p.start()
p.join()
这工作正常,并按应有的方式打印“hello bob”。但是,当我在 if 语句之前或之后向文件添加任何其他代码时,p 不会计算,并且我的文件循环回到开头并无休止地重新运行。例如,下面的代码给我这个问题:
from multiprocessing import Process
def f(name):
print('hello', name)
if __name__ == '__main__':
p = Process(target=f, args=('bob'))
p.start()
p.join()
test_input = input("test input")
我 运行 Python 使用 Windows 10、Pycharm v. 2021.3.2 和 Python 3.10.0。这是你们以前见过的问题吗?在这一点上,我开始怀疑它是否甚至是 Windows 和 Pycharm 或 Windows 和 Python 之间的问题,或者可能只是我缺乏经验的情况.
谢谢!
那个if __name__ == '__main__':
后卫很重要。在不使用 fork
的系统上,它通过在每个工作进程 中导入主脚本来模拟一个 fork
而没有 将其命名为 __main__
(它是名为 __mp_main__
IIRC)。任何在“主”脚本中只应 运行 的代码都需要受到该守卫的保护(它可以通过定义一个函数并在受保护的段内调用它来间接保护;该函数将在工作人员中定义,但不是 运行).
因此,要解决此问题,您需要做的就是缩进 test_input = input("test input")
,以便它受到 if __name__ == '__main__':
守卫的保护。在实际代码中,我尽量保持受保护的部分干净(这样我就不会意外地编写依赖全局状态的函数,当它不是 运行 作为主脚本时不存在,并且为了温和的性能优势在全局变量上使用函数局部变量),所以我会这样写:
from multiprocessing import Process
def f(name):
print('hello', name)
def main():
p = Process(target=f, args=('bob',))
p.start()
p.join()
test_input = input("test input")
if __name__ == '__main__':
main()
但这并不是绝对必要的。
关于ShadowRanger的回答,我觉得你也应该在'bob'后面加上逗号。 根据https://docs.python.org/3/library/multiprocessing.html
P如果要另外声明的话应该是这样的
p = Process(target=f, args=('bob',))
我想我会详细说明 ShadowRanger 的回答:
在 Windows 系统上,新的子流程是通过以下步骤创建的:
- 创建了一个新进程,其中 Python 解释器是 re-launched。
- Python 解释器 re-interprets 当前源程序执行 全局范围内的所有内容 以编译函数定义、初始化全局变量等.
- 最后,您的辅助函数
f
在这种情况下被调用,内存因此被初始化。
将创建子进程的代码放在由 if __name__ == '__main__':
控制的块中的原因是,如果您不这样做,那么由于上面的第 2 步,您将进入递归的无限循环创建新的子流程 ad inifinitum。 重点是只有在main函数中,变量__name__
才会有值'__main__';对于创建的任何子流程,它将具有不同的值。 因此创建新子流程的代码,即 p = Process(target=f, args=('bob',))
,将不会作为子流程初始化的一部分执行。
您的问题是由于语句 test_input = input("test input")
在全局范围内 而 不在 if __name__ == '__main__':
块内,因此它将作为子进程的初始化。因此,您的工作函数 f
不会 运行 直到满足此输入提示,然后当它 returns 您的主进程将再次发出提示。无论如何,这是我在 Windows 命令提示符下 运行 时看到的。也许 PyCharm 限制了从主线程以外的任何线程执行 input 语句。但是,即使在创建子流程时从该语句中抛出异常,我仍然不太明白您的程序将如何连续循环。不幸的是,我没有安装 PyCharm。