pycharm Python多处理代码只能在终端或调试模式下运行

laik7k3q  于 8个月前  发布在  PyCharm
关注(0)|答案(3)|浏览(141)

我只能通过在终端中执行或在调试模式下运行以下代码。
看起来这是关于可移植性的问题(我猜),但有人能解释一下吗?
我看到一些教程强调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
zujrkrfu

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,而且我只在小实验中使用交互模式。

xpszyzbs

xpszyzbs2#

我猜你是从软件包特殊的__main__.py文件中运行你的脚本,看起来pickle不能管理它。
尝试重命名你的文件到别的东西像mymod.py然后运行python -m mypkg/mymod

mrphzbgm

mrphzbgm3#

看起来是PyCharm中运行配置的问题。当我复制粘贴你的代码时,它在我的机器上正常执行(PyCharm 2023.2,Windows 11)。
您的运行配置中是否有一些特殊的内容?
PS:对不起,我发布这个作为一个答案-还没有权限评论。

相关问题