5

我一直在阅读和重新阅读 IPython 文档/教程,但我无法弄清楚这段特定代码的问题。似乎该函数dimensionless_run对传递给每个引擎的命名空间不可见,但我很困惑,因为该函数是在中定义的__main__,并且作为全局命名空间的一部分清晰可见。

wrapper.py:

import math, os

def dimensionless_run(inputs):
    output_file = open(inputs['fn'],'w')
    ...
    return output_stats

def parallel_run(inputs):
    import math, os  ## Removing this line causes a NameError: global name 'math'
                     ## is not defined.
    folder = inputs['folder']
    zfill_amt = int(math.floor(math.log10(inputs['num_iters'])))
    for i in range(inputs['num_iters']):
        run_num_str = str(i).zfill(zfill_amt)
        if not os.path.exists(folder + '/'):
            os.mkdir(folder)
        dimensionless_run(inputs)
    return

if __name__ == "__main__":
    inputs = [input1,input2,...]
    client = Client()
    lbview = client.load_balanced_view()
    lbview.block = True
    for x in sorted(globals().items()):
        print x
    lbview.map(parallel_run,inputs)

ipcluster start --n=6在生成排序后的全局字典之后执行此代码,包括mathandos模块和parallel_runanddimensionless_run函数。紧随其后的是 IPython.parallel.error.CompositeError: an or more exceptions from call to method: parallel_run,由大量的 组成[n:apply]: NameError: global name 'dimensionless_run' is not defined,其中 n 从 0 到 5 运行。

有两件事我不明白,它们显然是相关的。

  1. 为什么代码没有dimensionless_run在全局命名空间中识别?
  2. 为什么import math, os需要在parallel_run的定义里面?

编辑:结果证明这根本不是命名空间错误——我ipcluster start --n=6在一个不包含代码的目录中执行。要修复它,我需要做的就是在我的代码目录中执行 start 命令。我还通过添加以下行来修复它:

    inputs = input_pairs
    os.system("ipcluster start -n 6") #NEW
    client = Client()
    ...
    lbview.map(parallel_run,inputs)
    os.system("ipcluster stop")       #NEW

在正确的位置启动所需的集群。

4

1 回答 1

8

这主要是与 IPython.parallel 的 Python 名称空间问题的重复,它有更详细的答案,但要点:

当客户端发送parallel_run到引擎时,它只发送该函数,而不是定义函数的整个命名空间(__main__模块)。因此,当运行 remote 时parallel_run,查找mathor osordimensionless_run将首先查找locals()(函数中已经定义的内容,即您的函数内导入),然后查找引擎上globals()__main__模块。

有多种方法可以确保名称在引擎上可用,但也许最简单的方法是显式定义/发送它们到引擎(交互式命名空间 __main__引擎上,就像在 IPython 中本地一样):

client[:].execute("import os, math")
client[:]['dimensionless_run'] = dimensionless_run

在进行跑步之前,在这种情况下,一切都应该按照您的预期进行。

这是以交互方式/在脚本中定义的模块独有的问题 - 如果此文件是模块而不是脚本,则不会出现,例如

from mymod import parallel_run
lbview.map(parallel_run, inputs)

在这种情况下globals(),模块全局变量通常在任何地方都是相同的。

于 2012-09-06T20:17:08.050 回答