Python 变量在 if __name__ == '__main__'之后未定义



我试图通过使用multiprocessing库中的Pool来分配查找历史股票价格数据的任务。

这个工作很好,直到我试图使用我得到的数据。我定义了hist_price函数,它输出一个字典列表pcl。我可以print(pcl),它是完美的,但是如果我在if __name__=='__main__':块之后尝试print(pcl),它就会爆炸,说pcl是未定义的。我已经尝试在几个地方声明global pcl,但它没有区别。

from multiprocessing import Pool
syms = ['List', 'of', 'symbols']
def hist_price(sym):
    #... lots of code looking up data, calculations, building dicts...
    stlh = {"Sym": sym, "10D Max": pcmax, "10D Min": pcmin} #simplified
    return stlh
#global pcl
if __name__ == '__main__':
    pool = Pool(4)
    #global pcl
    pcl = pool.map(hist_price, syms)
    print(pcl) #this works
    pool.close() 
    pool.join()
print(pcl) #says pcl is undefined
#...rest of my code, dependent on pcl...

我也试过删除if __name__=='__main__':块,但它给了我一个RunTimeError告诉我具体把它放回去。是否有其他方法调用变量使用if块之外?

我认为你的问题有两部分。第一个是"当前代码中的pcl有什么问题?",第二个是"为什么我需要if __name__ == "__main__"保护块?"

让我们按顺序来处理它们。pcl变量的问题是它只在if块中定义,所以如果模块被加载而没有作为脚本运行(这是设置__name__ == "__main__"的内容),则在后面的代码运行时不会定义它。

要解决这个问题,您可以更改代码的结构。最简单的修复方法是保护if __name__ == "__main__"块中使用pcl的其他代码位(例如,也许将它们全部缩进到当前块下)。另一种修复方法是将使用pcl的代码放入函数中(可以在保护块外声明),然后从if __name__ == "__main__"块内调用这些函数。它看起来像这样:

def do_stuff_with_pcl(pcl):
    print(pcl)
if __name__ == "__main__":
    # multiprocessing code, etc
    pcl = ...
    do_stuff_with_pcl(pcl)

至于为什么这个问题首先出现,最终原因是在Windows上使用multiprocessing模块。您可以在文档中阅读有关该问题的信息。

当multiprocessing为它的Pool创建一个新进程时,它需要用当前模块状态的副本初始化该进程。因为Windows没有fork(它会自动将父进程的内存复制到子进程中),所以Python需要从头开始设置所有内容。在每个子进程中,它从它的文件中加载模块,如果你的模块的顶层代码试图创建一个新的Pool,你会有一个递归的情况,每个子进程将开始产生一套自己的全新的子进程。

multiprocessing代码有一些防范措施,我认为(所以你不会因为简单的粗心而fork bomb自己),但是你仍然需要自己做一些工作,通过使用if __name__ == "__main__"来保护任何不应该在子进程中运行的代码。

相关内容

  • 没有找到相关文章

最新更新