我只能通过在终端中执行或在调试模式下运行以下代码。
看起来这是关于可移植性的问题(我猜),但有人能解释一下吗?
我看到一些教程强调if __name__ == '__main__':
的重要性,但作为一个python新手,我很难理解。
提前多谢了。
import multiprocessing as mp
def add_abc(a, b, c):
print(a + b + c)
def main():
# Create a list of information
a = [1, 2, 3, 4, 5]
b = [6, 7, 8, 9, 10]
c = [11, 12, 13, 14, 15]
processes = []
# Create a list of processes
for i in range(5):
p = mp.Process(target=add_abc, args=(a[i], b[i], c[i]))
processes.append(p)
# Start the processes
for p in processes:
p.start()
# Join the processes
for p in processes:
p.join()
if __name__ == '__main__':
main()
如果我在pycharm的正常运行模式下运行它(Shift + F10),我会得到EOFError
和_pickle.PicklingError
:(错误信息的一部分)
File "D:\Program Files\Python311\Lib\multiprocessing\popen_spawn_win32.py", line 94, in __init__
reduction.dump(process_obj, to_child)
File "D:\Program Files\Python311\Lib\multiprocessing\reduction.py", line 60, in dump
ForkingPickler(file, protocol).dump(obj)
_pickle.PicklingError: Can't pickle <function add_abc at 0x0000023408E3C540>: attribute lookup add_abc on __main__ failed
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "D:\Program Files\Python311\Lib\multiprocessing\spawn.py", line 120, in spawn_main
exitcode = _main(fd, parent_sentinel)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\Program Files\Python311\Lib\multiprocessing\spawn.py", line 130, in _main
self = reduction.pickle.load(from_parent)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
EOFError: Ran out of input
正常输出应为:
18
21
24
27
30
3条答案
按热度按时间zujrkrfu1#
这可能是IDE的问题。Python有两种操作模式:正常和互动。可以把普通模式想象成从终端运行一个“.py”文件,而交互模式则是在提示符中一次键入一行代码。多处理也有两种不同的操作模式,它们受到这种正常和交互式操作的影响:产卵和分叉。分叉在Windows上不可用,在MacOS上也不是默认设置。这个问题听起来像是在交互模式下运行python而在生成模式下使用多处理之间的糟糕交互。
为什么需要
if __name__ == "__main__":
当您尝试“生成”一个新进程时,它将尝试
import
创建它的主文件。如果导入脚本就像运行它一样,那么导入脚本将导致它尝试创建自己的子进程,该子进程将导入-创建一个新进程-导入...导致无限循环,这可能会创建无限的子进程。这就是为什么我们使用if __name__ == "__main__":
来防止脚本创建任何子进程(或者做任何除了定义函数类和一些静态数据之外的事情)。__name__
是一个特殊的变量,只有在运行该文件时才是"__main__"
。如果文件被导入,它将是“模块”的名称(本例中的文件名:“测试”)。我认为实际的错误信息是:
如果使用交互模式,主要问题也与导入有关。根据IDE的不同,您可能甚至没有意识到您正在使用交互模式,但是如果您正在使用交互模式,那么当子进程启动时,python没有要导入的“main”文件。基本上,当一个新进程通过“spawn”启动时,它对其父进程一无所知。它只有一个“管道”来与父节点通信,它知道它需要遵循标准的python“spawn”启动过程(来自:python\lib\multiprocessing\spawn.py)。父进程将尝试通过该管道发送子进程执行您想要的内容所需的信息,但还有一个小细节。所使用的通信协议(“Pickle”)不能直接发送函数或类定义。相反,它发送关于如何导入正确定义的指令。最后,我们来到这个问题:如果在交互模式下定义函数,则没有“.py”文件要导入。有时你可以通过把目标函数放在一个单独的文件中来解决这个问题,这个文件可以被导入,有时IDE会用一些黑魔法让它以一种非标准的方式工作。通常,我只喜欢使用只执行文件代码的IDE,而且我只在小实验中使用交互模式。
xpszyzbs2#
我猜你是从软件包特殊的
__main__.py
文件中运行你的脚本,看起来pickle不能管理它。尝试重命名你的文件到别的东西像mymod.py然后运行
python -m mypkg/mymod
mrphzbgm3#
看起来是PyCharm中运行配置的问题。当我复制粘贴你的代码时,它在我的机器上正常执行(PyCharm 2023.2,Windows 11)。
您的运行配置中是否有一些特殊的内容?
PS:对不起,我发布这个作为一个答案-还没有权限评论。