如果 __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__"