新年快乐!在
我是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()
好的,我不知道
get_ipython.magic
调用的作用,但是在没有人知道的情况下,让我们看看Windows上的多处理是如何工作的,以及为什么这一行:可能是错的。很可能,这应该隐藏在稍后进行的相同
if __name__ == '__main__'
测试之下。在(如果移动代码行可以解决问题,可以到此为止,但是如果您想有效地使用多处理代码,那么下面的内容值得一读。)
当您创建
multiprocessing.Process
或Pool
实例时,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运行这个特殊的},它连接回您的Python进程,即您自己启动的进程。从Python中,新的Python获得原始主模块的名称,并将其导入到。在
main
或{它使用一个常规的旧的}或您命名的{}文件。这允许多处理代码访问整个程序。在
import
来导入它(好吧,有一个特殊的稍微被黑掉的导入,而且细节也会因Python版本的不同而有所不同)。这意味着__name__
不是__main__
,而是main
或{接下来,多处理代码将确定您希望从哪个模块运行哪个函数。(这一切都是通过
pickle
系统来处理的,这就是为什么你只能运行可以被pickle的函数,传递可以被pickle的参数。)在你的原始Python和这个运行进程的新Python之间设置了所需的所有通信之后,新Python现在可以调用该函数,让它自己去做,当它返回时,让新的Python进程终止。在所有这一切都取决于这样一个事实:当新的Python进程运行}或任何能加载原始程序的东西时,它的可执行代码会受到使用 的测试的保护。这可以确保编写程序的主要工作程序-不会在衍生的子Python中运行。相反,只有}实际上运行。主程序中的所有内容都会被导入并定义,这样所有函数的名称一旦通过pickling代码显示出来,就可以被调用了。但他们中没有一个跑过。在
import main
或{if __name__
multiprocessing.main
或{您可以违反此规则,1并运行特定的代码位,只有当它们不中断运行
Process
实例所需的设置序列时。从这里看到的问题来看,get_ipython.magic('reset -sf')
破坏了设置顺序,这一点似乎已经足够清楚了。在1有一种情况是,必须运行特定的代码位,如果必须扩充
sys.path
来插入导入某些代码的位置。在相关问题 更多 >
编程相关推荐