为什么池.连接()使用IPython magic%reset清除变量空间时挂起?

2024-09-29 23:19:19 发布

您现在位置:Python中文网/ 问答频道 /正文

新年快乐!在

我是Pythonmultiprocessing模块的新手。为了更好地理解apply_async是如何工作的,我在下面写下了简短的脚本。除非我注释掉第二行(get_ipython().magic('reset -sf')),否则脚本将挂起。 有人能告诉我为什么会这样吗?我使用Spyder IDE在Python3.5下工作。在

我之所以使用IPython magic%reset是因为我想在运行脚本之前清除所有变量,并且我在this webpage上读到IPython magic%reset相当于Matlab/Octave中的clear all。在

提前感谢您的帮助!在

from IPython import get_ipython
get_ipython().magic('reset -sf')
import random
import multiprocessing

def stakhanov(chunk_idx):
    data=random.randint(1,10) # create random integer between 1 and 10:
    frame_idx=chunk_idx
    return (frame_idx,data)

def stakhanov_finished(result):
    (frame_idx,data)=result
    DATA_READ[frame_idx]=data

def start_multiprocess_io():
    pool = multiprocessing.Pool(NUM_PROCESSES)  # create pool of all processes:
    chunk_idx = 0
    for i in range(NUM_PROCESSES):
        pool.apply_async(stakhanov,args=(chunk_idx,),callback=stakhanov_finished)
        chunk_idx += 1
    pool.close()
    pool.join() 

if __name__ == '__main__':
    global NUM_PROCESSES, DATA_READ
    NUM_PROCESSES = multiprocessing.cpu_count() # number of CORES
    DATA_READ = [None for _ in range(NUM_PROCESSES)] # declare list
    start_multiprocess_io()

Tags: import脚本datagetipythonrandomframenum
1条回答
网友
1楼 · 发布于 2024-09-29 23:19:19

好的,我不知道get_ipython.magic调用的作用,但是在没有人知道的情况下,让我们看看Windows上的多处理是如何工作的,以及为什么这一行:

get_ipython().magic('reset -sf')

可能是错的。很可能,这应该隐藏在稍后进行的相同if __name__ == '__main__'测试之下。在

(如果移动代码行可以解决问题,可以到此为止,但是如果您想有效地使用多处理代码,那么下面的内容值得一读。)


当您创建multiprocessing.ProcessPool实例时,multiprocessing模块为新进程生成一个额外的Python实例。这与Linux类似,只是没有fork,因此它不能复制当前的进程。这个新生成的进程是一个全新的、全新的、空的Python。在

到目前为止,空的Python使用特定的参数运行。在Python2.7和Python3.6+之间,它们有些不同;这里,我将引用2.7中相当长的一段:

^{pr2}$

3.6代码将其拆分一点,has this fragment

^{3}$

不管怎样,此时发生的情况是新Python应该从multiprocessing导入一个模块并在该模块中运行一个函数。函数main()spawn_main(),从创建它的进程加载一些信息-您的进程,以找出运行的程序。在

如果您使用的是冻结的Python,这一切可能取决于您import multiprocessing并调用freeze_support。这是if getattr(sys, 'frozen', False)测试的第一个分支:这里正在解决的问题是-c 'from multiprocessing ...'选项在冻结的Python中不起作用。(如果不使用冻结的Python,-c行可以处理大多数事情。)

总之,结果是新的Python运行这个特殊的main或{},它连接回您的Python进程,即您自己启动的进程。从Python中,新的Python获得原始主模块的名称,并将其导入到。在

它使用一个常规的旧的import来导入它(好吧,有一个特殊的稍微被黑掉的导入,而且细节也会因Python版本的不同而有所不同)。这意味着__name__不是__main__,而是main或{}或您命名的{}文件。这允许多处理代码访问整个程序。在

接下来,多处理代码将确定您希望从哪个模块运行哪个函数。(这一切都是通过pickle系统来处理的,这就是为什么你只能运行可以被pickle的函数,传递可以被pickle的参数。)在你的原始Python和这个运行进程的新Python之间设置了所需的所有通信之后,新Python现在可以调用该函数,让它自己去做,当它返回时,让新的Python进程终止。在

所有这一切都取决于这样一个事实:当新的Python进程运行import main或{}或任何能加载原始程序的东西时,它的可执行代码会受到使用if __name__的测试的保护。这可以确保编写程序的主要工作程序-不会在衍生的子Python中运行。相反,只有multiprocessing.main或{}实际上运行。主程序中的所有内容都会被导入并定义,这样所有函数的名称一旦通过pickling代码显示出来,就可以被调用了。但他们中没有一个跑过。在

您可以违反此规则,1并运行特定的代码位,只有当它们不中断运行Process实例所需的设置序列时。从这里看到的问题来看,get_ipython.magic('reset -sf')破坏了设置顺序,这一点似乎已经足够清楚了。在


1有一种情况是,必须运行特定的代码位,如果必须扩充sys.path来插入导入某些代码的位置。在

相关问题 更多 >

    热门问题