python变量存在于locals中,但是NameError:“未定义全局名称'tb'”

时间:2014-03-07 01:48:56

标签: python

所以在下面的代码中我得到tb没有定义,但是当我使用pdb时,我看到tb已定义,并且本地也在populatingNodeSlotPort函数的本地范围内填充了一堆值。

这是scenarioUniform1PartA.py文件

import json
import sbt
import sys
sys.path.append('staging/mgmt/ifc/ishell/')


def Get_Test_Block():
    import inspect
    for Entry in inspect.stack():
        Args = inspect.getargvalues(Entry[0])
        # print 'Args is ', Args
            if Args[3].has_key('self') and hasattr(
                Args[3]['self'],'Test_Block_Yaml_Data'):
            return Args[3]['self']
        raise ValueError, 'Could not determine current test block.'

def load(scenarioObj):
    scenarioInit(scenarioObj)
    log = logging.getLogger('sbt')
    vmTopo = []
    readScale(scenarioObj)
    tb = Get_Test_Block()
    tb.Harness_Object.Build_Mo_Objects()
    # manipulating values of some variables here 

    return locals()

接下来是scenarioUniform1.py文件

from scenarioUniform1PartA import *

def populatingNodeSlotPort(scenarioObj):
    for k,v in load(scenarioObj).items():
        vars()[k] = v
    tbType = 'unknown'
    import pdb;pdb.set_trace()
    tbType = tb.Nodes.Get_Nodes_By_Type(Defines.NODE_TYPE_LEAF)[0]['Mode']

pdb trackback

> /local/vchauhan/updatedBox/mgmt.git/test/system/sbt/scenarioUniform1.py(28)populatingNodeSlotPort()
-> tbType = tb.Nodes.Get_Nodes_By_Type(Defines.NODE_TYPE_LEAF)[0]['Mode']
(Pdb) print tb
<Classes_ScenarioLoad.ScenarioLoad object at 0x49dab50>
(Pdb) locals()['tb']
<Classes_ScenarioLoad.ScenarioLoad object at 0x49dab50>
(Pdb) n
NameError: "global name 'tb' is not defined"
> /local/vchauhan/updatedBox/mgmt.git/test/system/sbt/scenarioUniform1.py(28)populatingNodeSlotPort()

供参考

(Pdb) locals()
{'vmTopologyFileName': '/tmp/vmm_topos.yml', 'new_size': 1, 'nodeToBeDecomCom': 3, 'vmTopo': [{'VCenter_List': [{'Name': 'vserver51-222'}], 'ESX_List': [{'VCenter': 'vserver51-222', 'Name': 'esx51-443'}, {'VCenter': 'vserver51-222', 'Name': 'esx51-444'}], 'Connection_List': [{'Dest': 'leaf1', 'Source': 'esx51-443'}, {'Dest': 'leaf2', 'Source': 'esx51-444'}], 'VShield_List': [{'Name': 'vshield51-222'}], 'VM_List': [{'Name': 'c6-222'}, {'Name': 'd6-222'}]}], 'size': 4, 'vmTopoName': 'vchauhan', 'log': <logging.Logger instance at 0x30abb90>, 'scenarioObj': <sbt.Scenario object at 0x337c790>, 'nodeId': 1, 'nodeToBeShutdown': 2, 'clusterShardInstanceStepCounter': 4, 'unWiredIfcCount': 2, 'tb': <Classes_ScenarioLoad.ScenarioLoad object at 0x49dab50>, 'applyOnIfc': 1, 'halfUnWiredIfcCount': 2, 'Command_String': '../../tools/res.py sh -s vchauhan', '__exception__': (<type 'exceptions.NameError'>, "global name 'tb' is not defined"), 'tbType': 'unknown', 'Output': '--------------------------------------------------------------------------------\n6 are in production\n--------------------------------------------------------------------------------\nDevice Name      Type     IP              Reserved By            Other Info\n--------------------------------------------------------------------------------\nvserver51-222    vcenter  192.168.82.249  vchauhan               \nesx51-443        esx      192.168.81.145  vchauhan               multiPnic\nesx51-444        esx      192.168.81.146  vchauhan               multiPnic\nvshield51-222    vshield  192.168.81.162  vchauhan               \nc6-222           pc       0.0.0.0         vchauhan               \nd6-222           pc       0.0.0.0         vchauhan               \n--------------------------------------------------------------------------------\n\n', 'wiredIfcCount': 1, 'wiNodeStepCounter': 20, 'i': 2, 'k': 'applianceClusterPolStepCounter', 'temp_size': 1, 'v': 100, 'pdb': <module 'pdb' from '/usr/lib64/python2.6/pdb.pyc'>, 'applianceClusterPolStepCounter': 100}

3 个答案:

答案 0 :(得分:1)

首先,您遇到调试问题这一事实正是不应该这样做的原因。为什么要把变量注入locals()呢?只需使用dict直接提供给您的load(scenarioObj)

my_dict = load(scenarioObj)
my_dict['tb'].Nodes.whatever...

您应该同样远离return中的locals() load明确地以任何形式返回您需要的数据... dict,namedtuple,自定义类。不管。


发生这种情况的原因是你“擅长”翻译。考虑两个看似等效的函数:

def f():
    x = []
    x.append(1)


def g():
    locals()['x'] = [] #n.b. locals() is equivalent to vars()
    x.append(1)

同样的事,对吧?不。

dis.dis(f)
  2           0 BUILD_LIST               0 
              3 STORE_FAST               0 (x) 

  3           6 LOAD_FAST                0 (x) #NOTE: loading x as a LOCAL
              9 LOAD_ATTR                0 (append) 
             12 LOAD_CONST               1 (1) 
             15 CALL_FUNCTION            1 (1 positional, 0 keyword pair) 
             18 POP_TOP              
             19 LOAD_CONST               0 (None) 
             22 RETURN_VALUE         

dis.dis(g)
  2           0 BUILD_LIST               0 
              3 LOAD_GLOBAL              0 (locals) 
              6 CALL_FUNCTION            0 (0 positional, 0 keyword pair) 
              9 LOAD_CONST               1 ('x') 
             12 STORE_SUBSCR         

  3          13 LOAD_GLOBAL              1 (x) #NOTE: loading x as a GLOBAL
             16 LOAD_ATTR                2 (append) 
             19 LOAD_CONST               2 (1) 
             22 CALL_FUNCTION            1 (1 positional, 0 keyword pair) 
             25 POP_TOP              
             26 LOAD_CONST               0 (None) 
             29 RETURN_VALUE         

请参阅两个注释行 - 第一个函数认为x是本地的,第二个认为x全局。 python解释器假设您在调用方法之前未在函数范围内明确地为x分配了某些内容,必须引用全局。值得注意的是,当它编译函数时,它决定x是本地的还是全局的,这在你实际调用之前就已经完成了。因此,解释器绝对无法在当时检测到变量动态注入locals

答案 1 :(得分:1)

您确定要使用从函数返回的值自动修改局部变量等游戏吗?

为什么不返回dict并使用其中的值:

def load(scenarioObj):
    return {'tb': tb, ...}

...

def populatingNodeSlotPort(scenarioObj):
    data = load(scenarioObj)
    tb = data['tb']
    tbType = tb.Nodes.Get_Nodes_By_Type(Defines.NODE_TYPE_LEAF)[0]['Mode']

答案 2 :(得分:0)

如果要动态修改变量,请使用globals代替locals。修改locals字典并不能保证做任何事情。在CPython中,它肯定没有做任何事情。