如果 __name__ == '__main__' 之后未定义 Python 变量

Posted

技术标签:

【中文标题】如果 __name__ == \'__main__\' 之后未定义 Python 变量【英文标题】:Python variables not defined after if __name__ == '__main__'如果 __name__ == '__main__' 之后未定义 Python 变量 【发布时间】:2016-12-22 00:35:56 【问题描述】:

我正在尝试使用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 块之外使用吗?

【问题讨论】:

你有if __name__=='__main__':是因为你是从终端运行脚本还是其他原因? @MosesKoledoye 可能是因为 OP 正在使用多处理。 @poke 哦好的。显然是这样。 【参考方案1】:

我认为您的问题有两个部分。第一个是“当前代码中的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 模块。您可以在the documentation 中阅读有关该问题的信息。

当多处理为其Pool 创建一个新进程时,它需要使用当前模块状态的副本初始化该进程。因为 Windows 没有 fork(它会自动将父进程的内存复制到子进程中),所以 Python 需要从头开始设置所有内容。在每个子进程中,它从其文件中加载模块,如果您模块的***代码尝试创建一个新的Pool,您将遇到递归情况,每个子进程都会开始生成一个全新的一组自己的子进程。

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

【讨论】:

这个过程在我的代码开头附近运行,其余部分依赖于pcl。如果可以的话,我希望避免将我的其余代码全部放在 if 块中。我尝试在if 块之外声明pcl(有和没有global),但它似乎仍将其视为两个单独的实例。 @wampthing2:我已经更新了我的答案,以深入了解问题所在以及如何解决问题的更多细节。排序:不要在顶层做太多事情,因为你需要用if __name__ == "__main__" 来保护它。

以上是关于如果 __name__ == '__main__' 之后未定义 Python 变量的主要内容,如果未能解决你的问题,请参考以下文章

即使添加了“如果 __name__ == '__main__':”,Windows 上的 python joblib Parallel 也无法正常工作

Windows 上的 python 多处理,如果 __name__ == "__main__"

关于__name__=='__main__'的理解

if __name__ == '__main__' 含义

if __name__ == '__main__' 应用场景

if __name__ =="__main__"