摘要:循環(huán)中當(dāng)為時,將對象返回并作為全局變量的內(nèi)容是字符串,接下來,報錯。幸運的是,代碼修改以后,執(zhí)行正常,我也找到了一些文章來解釋這個問題,我的第一感覺也沒有錯,的確是變量作用域的問題,代碼在執(zhí)行過程中,實際上是在訪問,而不是我們期望的。
使用python有些年頭了,自認為對Python的基本知識很了解了,今天發(fā)生的一件事讓我對Python有了更多的認識,寫成文章做個記錄。
同事讓我?guī)兔匆韵乱欢未a,具體內(nèi)容和函數(shù)名字可以不用太過在意,命名上做了一些特殊處理,但是不影響代碼邏輯和要表達的意思。
for循環(huán)中當(dāng)node_type為fb時,將FBX對象返回并作為全局變量dut(node_name的內(nèi)容是字符串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刪除掉,代碼執(zhí)行正常。
聽到這里,我的第一反應(yīng)是變量作用域的問題,但是也無法道出其中原委,于是建議同事,將context manager那一段代碼改成with cli_ctx as d,重新嘗試一下是否有問題,同時我在網(wǎng)上繼續(xù)搜索相關(guān)的原因,之后由結(jié)果和理論結(jié)合分析問題的原因。
幸運的是,代碼修改以后,執(zhí)行正常,我也找到了一些文章來解釋這個問題,我的第一感覺也沒有錯,的確是變量作用域的問題,代碼在執(zhí)行過程中,print dut實際上是在訪問Local variable,而不是我們期望的global variable dut。
參考Python的官方文檔和搜索到的資料,總結(jié)出具體原因如下。
當(dāng)搜索一個變量的時候,先從局部作用域開始搜索,如果在局部作用域沒有找到那個變量,就會在全局變量中找這個變量,如果找不到拋出異常Unbound-LocalError。
如果內(nèi)部函數(shù)有引用外部函數(shù)的同名變量或者全局變量,并且對這個變量有修改,那么python會認為它是一個局部變量。因為對變量的定義在代碼塊以外,當(dāng)前代碼塊中沒有變量的定義和賦值,所以報錯。
在我們的代碼中,全局變量dut雖然創(chuàng)建了,但是由于在函數(shù)代碼塊中,下文中有context manager cli_ctx對變量dut進行了賦值操作,導(dǎo)致在函數(shù)block中,dut成為了局部變量,而非全局變量。
對變量賦值的操作=是很明顯的語句,其他不是那么明顯的賦值操作有:for循環(huán)中的賦值,except語句中的賦值,with...as...{var}中的var。
大坑啊,基礎(chǔ)不夠牢靠還是。
ReferencePython 2.7.13 Documentation - Language Reference - 4. Execution Model
Stackoverflow - Short Description of the Scoping Rules?
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/40662.html
摘要:正如儒家經(jīng)典所闡述修身齊家治國平天下。除此之外,模塊還有如下最基本的屬性在一個模塊的全局空間里,有些屬性是全局起作用的,稱之為全局變量,而其它在局部起作用的屬性,會被稱為局部變量。 導(dǎo)讀:Python貓是一只喵星來客,它愛地球的一切,特別愛優(yōu)雅而無所不能的 Python。我是它的人類朋友豌豆花下貓,被授權(quán)潤色與發(fā)表它的文章。如果你是第一次看到這個系列文章,那我強烈建議,請先看看它寫的前...
摘要:正如儒家經(jīng)典所闡述修身齊家治國平天下。除此之外,模塊還有如下最基本的屬性在一個模塊的全局空間里,有些屬性是全局起作用的,稱之為全局變量,而其它在局部起作用的屬性,會被稱為局部變量。 導(dǎo)讀:Python貓是一只喵星來客,它愛地球的一切,特別愛優(yōu)雅而無所不能的 Python。我是它的人類朋友豌豆花下貓,被授權(quán)潤色與發(fā)表它的文章。如果你是第一次看到這個系列文章,那我強烈建議,請先看看它寫的前...
摘要:本文章旨在總結(jié)開發(fā)過程中碰到的容易忘記或者比較重要的坑,一方面加深自己對于該部分的理解,另一方面希望能夠分享給大家,知識在于分享,當(dāng)然踩過的坑也不例外滑稽。 在日常工作中,時常會碰到各種各樣的坑,有時真的覺得很多時候開發(fā)的經(jīng)驗都是踩坑踩出來的。在通往大牛的道路上,希望自己能夠跨越重重阻礙,越走越遠。學(xué)會時常總結(jié),不斷提升自己。 本文章旨在總結(jié)開發(fā)過程中碰到的容易忘記或者比較重要的坑,...
閱讀 1711·2021-11-22 12:09
閱讀 1452·2019-08-30 13:22
閱讀 2083·2019-08-29 17:00
閱讀 2635·2019-08-29 16:28
閱讀 2945·2019-08-26 13:51
閱讀 1174·2019-08-26 13:25
閱讀 3238·2019-08-26 12:14
閱讀 3007·2019-08-26 12:14