简体   繁体   English

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

[英]Python variables not defined after if __name__ == '__main__'

I'm trying to divvy up the task of looking up historical stock price data for a list of symbols by using Pool from the multiprocessing library. 我正在尝试通过使用multiprocessing库中的Pool来划分查找历史股票价格数据以获取交易品种列表的任务。

This works great until I try to use the data I get back. 在我尝试使用获取的数据之前,这非常有用。 I have my hist_price function defined and it outputs to a list-of-dicts pcl . 我定义了hist_price函数,它输出到字典列表pcl I can print(pcl) and it has been flawless, but if I try to print(pcl) after the if __name__=='__main__': block, it blows up saying pcl is undefined. 我可以print(pcl)并且它没有问题,但是如果我尝试在if __name__=='__main__':块之后print(pcl) ,它会炸毁,表示pcl是未定义的。 I've tried declaring global pcl in a couple places but it doesn't make a difference. 我试过在几个地方声明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...

I've also tried removing the if __name__=='__main__': block but it gives me a RunTimeError telling me specifically to put it back. 我也尝试过删除if __name__=='__main__':块,但是它给了我if __name__=='__main__':告诉我要放回去。 Is there some other way to call variables to use outside of the if block? 还有其他方法可以调用变量以在if块之外使用吗?

I think there are two parts to your issue. 我认为您的问题有两个部分。 The first is "what's wrong with pcl in the current code?", and the second is "why do I need the if __name__ == "__main__" guard block at all?". 第一个是“当前代码中的pcl怎么了?”,第二个是“为什么我需要if __name__ == "__main__"保护块?”。

Lets address them in order. 让我们按顺序解决它们。 The problem with the pcl variable is that it is only defined in the if block, so if the module gets loaded without being run as a script (which is what sets __name__ == "__main__" ), it will not be defined when the later code runs. pcl变量的问题在于,它仅在if块中定义,因此,如果模块加载时没有作为脚本运行(这是设置__name__ == "__main__" ),则稍后将不定义它代码运行。

To fix this, you can change how your code is structured. 要解决此问题,您可以更改代码的结构。 The simplest fix would be to guard the other bits of the code that use pcl within an if __name__ == "__main__" block too (eg indent them all under the current block, perhaps). 最简单的解决方法是同样在if __name__ == "__main__"块中保护使用pcl的代码的其他位(例如,将它们全部缩进当前块中)。 An alternative fix would be to put the code that uses pcl into functions (which can be declared outside the guard block), then call the functions from within an if __name__ == "__main__" block. 另一种解决方法是将使用pcl的代码放入函数中(可以在保护块外部声明),然后从if __name__ == "__main__"块中调用函数。 That would look something like this: 看起来像这样:

def do_stuff_with_pcl(pcl):
    print(pcl)

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

As for why the issue came up in the first place, the ultimate cause is using the multiprocessing module on Windows. 至于为什么首先出现此问题,最终原因是在Windows上使用了multiprocessing模块。 You can read about the issue in the documentation . 您可以在文档中阅读有关该问题的信息

When multiprocessing creates a new process for its Pool , it needs to initialize that process with a copy of the current module's state. 当多处理为其Pool创建新进程时,它需要使用当前模块状态的副本来初始化该进程。 Because Windows doesn't have fork (which copies the parent process's memory into a child process automatically), Python needs to set everything up from scratch. 由于Windows没有fork (可自动将父进程的内存复制到子进程中),因此Python需要从头开始进行所有设置。 In each child process, it loads the module from its file, and if you the module's top-level code tries to create a new Pool , you'd have a recursive situation where each of the child process would start spawning a whole new set of child processes of its own. 在每个子进程中,它将从文件中加载模块,如果模块的顶级代码尝试创建新的Pool ,则将出现递归的情况,其中每个子进程将开始产生一组新的自己的子进程。

The multiprocessing code has some guards against that, I think (so you won't fork bomb yourself out of simple carelessness), but you still need to do some of the work yourself too, by using if __name__ == "__main__" to guard any code that shouldn't be run in the child processes. 我认为, multiprocessing代码对此有一些防范措施(因此,您不会出于粗心大意而自行炸弹 ),但是您仍然需要自己做一些工作,使用if __name__ == "__main__"来进行防范任何不应在子进程中运行的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM