摘要:循环中当为时,将对象返回并作为全局变量的内容是字符串,接下来,报错。幸运的是,代码修改以后,执行正常,我也找到了一些文章来解释这个问题,我的第一感觉也没有错,的确是变量作用域的问题,代码在执行过程中,实际上是在访问,而不是我们期望的。
使用python有些年头了,自认为对Python的基本知识很了解了,今天发生的一件事让我对Python有了更多的认识,写成文章做个记录。
同事让我帮忙看以下一段代码,具体内容和函数名字可以不用太过在意,命名上做了一些特殊处理,但是不影响代码逻辑和要表达的意思。
for循环中当node_type为fb时,将FBX对象返回并作为全局变量dut(node_name的内容是字符串dut),接下来print dut,报错。
def setup_module(module): with step("Set_setup"): function_1_run(topo_info) function_2_run(topo_info) function_3_run(topo_info, set_resource, "device_config") for node in topo_info.nodes: if node.type == "fb": globals()[node.name] = FBX(node.manage_ip,"admin","111111") print node.name print globals()[node.name] print dut else: globals()[node.name] = Device() globals()[node.name].node_info = node if not get_config_file(topo_info, set_resource, "device_config"): test = dut print test with cli_ctx(dut) as dut: dut.cli.cmd_list = [ "configure", "interface fastEthernet 2", "ip address 192.168.1.5/24" ] dut.cli.exec_cmd() log.info("cli_ctx 1 end") export_firebox_topo(topo_info, set_resource, "device_config")
错误信息如下:
==================================== ERRORS ==================================== ___________________ ERROR at setup of some_module_1 ___________________ module =def setup_module(module): with step("Set_setup"): function_1_run(topo_info) function_2_run(topo_info) function_3_run(topo_info, set_resource, "device_config") for node in topo_info.nodes: if node.type == "fb": globals()[node.name] = FBX(node.manage_ip,"admin","111111") print node.name print globals()[node.name] > print dut E UnboundLocalError: local variable "dut" referenced before assignment some_name_python.py:54: UnboundLocalError ========================== 1 error in 155.62 seconds ===========================
同事提到,如果将with cli_ctx as dut这个block删除掉,代码执行正常。
听到这里,我的第一反应是变量作用域的问题,但是也无法道出其中原委,于是建议同事,将context manager那一段代码改成with cli_ctx as d,重新尝试一下是否有问题,同时我在网上继续搜索相关的原因,之后由结果和理论结合分析问题的原因。
幸运的是,代码修改以后,执行正常,我也找到了一些文章来解释这个问题,我的第一感觉也没有错,的确是变量作用域的问题,代码在执行过程中,print dut实际上是在访问Local variable,而不是我们期望的global variable dut。
参考Python的官方文档和搜索到的资料,总结出具体原因如下。
当搜索一个变量的时候,先从局部作用域开始搜索,如果在局部作用域没有找到那个变量,就会在全局变量中找这个变量,如果找不到抛出异常Unbound-LocalError。
如果内部函数有引用外部函数的同名变量或者全局变量,并且对这个变量有修改,那么python会认为它是一个局部变量。因为对变量的定义在代码块以外,当前代码块中没有变量的定义和赋值,所以报错。
在我们的代码中,全局变量dut虽然创建了,但是由于在函数代码块中,下文中有context manager cli_ctx对变量dut进行了赋值操作,导致在函数block中,dut成为了局部变量,而非全局变量。
对变量赋值的操作=是很明显的语句,其他不是那么明显的赋值操作有:for循环中的赋值,except语句中的赋值,with...as...{var}中的var。
大坑啊,基础不够牢靠还是。
ReferencePython 2.7.13 Documentation - Language Reference - 4. Execution Model
Stackoverflow - Short Description of the Scoping Rules?
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/40662.html
摘要:正如儒家经典所阐述修身齐家治国平天下。除此之外,模块还有如下最基本的属性在一个模块的全局空间里,有些属性是全局起作用的,称之为全局变量,而其它在局部起作用的属性,会被称为局部变量。 导读:Python猫是一只喵星来客,它爱地球的一切,特别爱优雅而无所不能的 Python。我是它的人类朋友豌豆花下猫,被授权润色与发表它的文章。如果你是第一次看到这个系列文章,那我强烈建议,请先看看它写的前...
摘要:正如儒家经典所阐述修身齐家治国平天下。除此之外,模块还有如下最基本的属性在一个模块的全局空间里,有些属性是全局起作用的,称之为全局变量,而其它在局部起作用的属性,会被称为局部变量。 导读:Python猫是一只喵星来客,它爱地球的一切,特别爱优雅而无所不能的 Python。我是它的人类朋友豌豆花下猫,被授权润色与发表它的文章。如果你是第一次看到这个系列文章,那我强烈建议,请先看看它写的前...
摘要:本文章旨在总结开发过程中碰到的容易忘记或者比较重要的坑,一方面加深自己对于该部分的理解,另一方面希望能够分享给大家,知识在于分享,当然踩过的坑也不例外滑稽。 在日常工作中,时常会碰到各种各样的坑,有时真的觉得很多时候开发的经验都是踩坑踩出来的。在通往大牛的道路上,希望自己能够跨越重重阻碍,越走越远。学会时常总结,不断提升自己。 本文章旨在总结开发过程中碰到的容易忘记或者比较重要的坑,...
阅读 1690·2021-11-22 12:09
阅读 1433·2019-08-30 13:22
阅读 2057·2019-08-29 17:00
阅读 2618·2019-08-29 16:28
阅读 2931·2019-08-26 13:51
阅读 1160·2019-08-26 13:25
阅读 3220·2019-08-26 12:14
阅读 2990·2019-08-26 12:14